diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 5681fe9625..0000000000 --- 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 67d52a4cec..d3c8c5e44c 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 fd484db6c8..b5a922f3d0 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 e9a8ce9c68..3092a9a7c7 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 68ce165ecc..6f8f060224 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 8d262c89dc..ffee74bccf 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' -include modulePrefix + 'library-common' -include modulePrefix + 'library-core' -include modulePrefix + 'library-dash' -include modulePrefix + 'library-extractor' -include modulePrefix + 'library-hls' -include modulePrefix + 'library-rtsp' -include modulePrefix + 'library-smoothstreaming' -include modulePrefix + 'library-transformer' -include modulePrefix + 'library-ui' -include modulePrefix + 'robolectricutils' -include modulePrefix + 'testutils' -include modulePrefix + 'testdata' -include modulePrefix + 'extension-av1' -include modulePrefix + 'extension-ffmpeg' -include modulePrefix + 'extension-flac' -include modulePrefix + 'extension-gvr' -include modulePrefix + 'extension-ima' -include modulePrefix + 'extension-cast' -include modulePrefix + 'extension-cronet' -include modulePrefix + 'extension-mediasession' -include modulePrefix + 'extension-media2' -include modulePrefix + 'extension-okhttp' -include modulePrefix + 'extension-opus' -include modulePrefix + 'extension-vp9' -include modulePrefix + 'extension-rtmp' -include modulePrefix + 'extension-leanback' -include modulePrefix + 'extension-workmanager' - 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' project(modulePrefix + 'library-ui').projectDir = new File(rootDir, 'library/ui') -project(modulePrefix + 'robolectricutils').projectDir = new File(rootDir, 'robolectricutils') -project(modulePrefix + 'testutils').projectDir = new File(rootDir, 'testutils') -project(modulePrefix + 'testdata').projectDir = new File(rootDir, 'testdata') + +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') + +include modulePrefix + 'robolectricutils' +project(modulePrefix + 'robolectricutils').projectDir = new File(rootDir, 'robolectricutils') +include modulePrefix + 'testdata' +project(modulePrefix + 'testdata').projectDir = new File(rootDir, 'testdata') +include modulePrefix + 'testutils' +project(modulePrefix + 'testutils').projectDir = new File(rootDir, 'testutils') diff --git a/demos/cast/build.gradle b/demos/cast/build.gradle index 8636c71ab0..2539e777c1 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 6bb16ed734..ebaab7bb24 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 080387db7e..2d3f606b8a 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.RenderersFactory; 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.CookieManager; 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 final class DemoUtil { 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 21dee820c9..48748f2c08 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.NonNull; 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.ext.ima.ImaAdsLoader; 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 @@ public class PlayerActivity extends AppCompatActivity 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 class PlayerActivity extends AppCompatActivity } @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 class PlayerActivity extends AppCompatActivity } } - 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 a66a1e0301..c655179fe3 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.Context; 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 @@ public class SampleChooserActivity extends AppCompatActivity 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 @@ public class SampleChooserActivity extends AppCompatActivity 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 5fd2890915..fab5b2070c 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 612e2fd37f..de9ea36f99 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 8b3ef2571e..01bf698455 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 41f2dff59c..661b198996 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); +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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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.
- -RtmpDataSourceFactory + +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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 b5bc931fd6..288afe5bcf 100644 --- a/docs/doc/reference/allclasses.html +++ b/docs/doc/reference/allclasses.html @@ -144,6 +144,8 @@
  • BasePlayer
  • BaseRenderer
  • BaseTrackSelection
  • +
  • BaseUrl
  • +
  • BaseUrlExclusionList
  • BehindLiveWindowException
  • BinaryFrame
  • BinarySearchSeeker
  • @@ -156,6 +158,7 @@
  • Buffer
  • Bundleable
  • Bundleable.Creator
  • +
  • BundleableUtils
  • BundledChunkExtractor
  • BundledExtractorsAdapter
  • BundledHlsMediaChunkExtractor
  • @@ -175,6 +178,7 @@
  • C.ColorTransfer
  • C.ContentType
  • C.CryptoMode
  • +
  • C.DataType
  • C.Encoding
  • C.FormatSupport
  • C.NetworkType
  • @@ -257,7 +261,7 @@
  • CronetDataSource.OpenException
  • CronetDataSourceFactory
  • CronetEngineWrapper
  • -
  • CronetEngineWrapper.CronetEngineSource
  • +
  • CronetUtil
  • CryptoInfo
  • Cue
  • Cue.AnchorType
  • @@ -350,6 +354,7 @@
  • DefaultLoadControl
  • DefaultLoadControl.Builder
  • DefaultLoadErrorHandlingPolicy
  • +
  • DefaultMediaDescriptionAdapter
  • DefaultMediaItemConverter
  • DefaultMediaItemConverter
  • DefaultMediaSourceFactory
  • @@ -409,6 +414,8 @@
  • DrmSessionManager
  • DrmSessionManager.DrmSessionReference
  • DrmSessionManagerProvider
  • +
  • DrmUtil
  • +
  • DrmUtil.ErrorSource
  • DtsReader
  • DtsUtil
  • DummyDataSource
  • @@ -440,8 +447,6 @@
  • EventMessageEncoder
  • EventStream
  • ExoDatabaseProvider
  • -
  • ExoFlags
  • -
  • ExoFlags.Builder
  • ExoHostedTest
  • ExoMediaCrypto
  • ExoMediaDrm
  • @@ -552,12 +557,15 @@
  • FlacSeekTableSeekMap
  • FlacStreamMetadata
  • FlacStreamMetadata.SeekTable
  • +
  • FlagSet
  • +
  • FlagSet.Builder
  • FlvExtractor
  • Format
  • Format.Builder
  • FormatHolder
  • ForwardingAudioSink
  • ForwardingExtractorInput
  • +
  • ForwardingPlayer
  • ForwardingTimeline
  • FragmentedMp4Extractor
  • FragmentedMp4Extractor.Flags
  • @@ -667,6 +675,9 @@
  • LoaderErrorThrower
  • LoaderErrorThrower.Dummy
  • LoadErrorHandlingPolicy
  • +
  • LoadErrorHandlingPolicy.FallbackOptions
  • +
  • LoadErrorHandlingPolicy.FallbackSelection
  • +
  • LoadErrorHandlingPolicy.FallbackType
  • LoadErrorHandlingPolicy.LoadErrorInfo
  • LoadEventInfo
  • LocalMediaDrmCallback
  • @@ -717,6 +728,7 @@
  • MediaMetadata
  • MediaMetadata.Builder
  • MediaMetadata.FolderType
  • +
  • MediaMetadata.PictureType
  • MediaParserChunkExtractor
  • MediaParserExtractorAdapter
  • MediaParserHlsMediaChunkExtractor
  • @@ -771,6 +783,7 @@
  • NalUnitUtil.PpsData
  • NalUnitUtil.SpsData
  • NetworkTypeObserver
  • +
  • NetworkTypeObserver.Config
  • NetworkTypeObserver.Listener
  • NonNullApi
  • NoOpCacheEvictor
  • @@ -804,9 +817,11 @@
  • PictureFrame
  • PlatformScheduler
  • PlatformScheduler.PlatformSchedulerService
  • +
  • PlaybackException
  • +
  • PlaybackException.ErrorCode
  • +
  • PlaybackException.FieldNumber
  • PlaybackOutput
  • PlaybackParameters
  • -
  • PlaybackPreparer
  • PlaybackSessionManager
  • PlaybackSessionManager.Listener
  • PlaybackStats
  • @@ -820,7 +835,7 @@
  • Player.Commands
  • Player.Commands.Builder
  • Player.DiscontinuityReason
  • -
  • Player.EventFlags
  • +
  • Player.Event
  • Player.EventListener
  • Player.Events
  • Player.Listener
  • @@ -899,6 +914,7 @@
  • ReusableBufferedOutputStream
  • RobolectricUtil
  • RtmpDataSource
  • +
  • RtmpDataSource.Factory
  • RtmpDataSourceFactory
  • RtpAc3Reader
  • RtpPacket
  • @@ -937,6 +953,8 @@
  • SeiReader
  • SequenceableLoader
  • SequenceableLoader.Callback
  • +
  • ServerSideInsertedAdsMediaSource
  • +
  • ServerSideInsertedAdsUtil
  • ServiceDescriptionElement
  • SessionAvailabilityListener
  • SessionCallbackBuilder
  • @@ -1054,6 +1072,7 @@
  • TimedValueQueue
  • Timeline
  • Timeline.Period
  • +
  • Timeline.RemotableTimeline
  • Timeline.Window
  • TimelineAsserts
  • TimelineQueueEditor
  • @@ -1136,7 +1155,6 @@
  • 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 f953bef48f..460a936697 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 @@ extends T

    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 @@ implements 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 @@ implements Constructors  -Constructor +Modifier +Constructor Description +protected BasePlayer
    ()   @@ -261,7 +263,9 @@ implements protected Player.Commands getAvailableCommands​(Player.Commands permanentAvailableCommands) -  + +
    Returns the Player.Commands available in the player.
    + int @@ -303,66 +307,61 @@ implements -Object -getCurrentTag() - -
    Deprecated. - -
    - - - 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.
    - -ExoPlaybackException -getPlaybackError() - -
    Deprecated. - -
    - - - + int getPreviousWindowIndex() -
    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 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.
    - + boolean hasNext() +
    Deprecated.
    + + + +boolean +hasNextWindow() +
    Returns whether a next window exists, which may depend on the current repeat mode and whether shuffle mode is enabled.
    - + boolean hasPrevious() +
    Deprecated.
    + + + +boolean +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 @@ implements 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.
    @@ -438,8 +436,7 @@ implements 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.
    @@ -451,26 +448,70 @@ implements void +seekBack() + +
    Seeks back in the current window by Player.getSeekBackIncrement() milliseconds.
    + + + +void +seekForward() + +
    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.
    - + +void +seekToNext() + +
    Seeks to a later position in the current or next window (if available).
    + + + +void +seekToNextWindow() + +
    Seeks to the default position of the next window, which may depend on the current repeat mode + and whether shuffle mode is enabled.
    + + + +void +seekToPrevious() + +
    Seeks to an earlier position in the current or previous window (if available).
    + + + +void +seekToPreviousWindow() + +
    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 @@ implements + void setMediaItem​(MediaItem mediaItem, boolean resetPosition) @@ -486,7 +527,7 @@ implements Clears the playlist and adds the specified MediaItem. - + void setMediaItem​(MediaItem mediaItem, long startPositionMs) @@ -494,7 +535,7 @@ implements Clears the playlist and adds the specified MediaItem. - + void setMediaItems​(List<MediaItem> mediaItems) @@ -502,14 +543,14 @@ implements + void setPlaybackSpeed​(float speed)
    Changes the rate at which playback occurs.
    - + void stop() @@ -529,7 +570,7 @@ implements 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 @@ implements
  • BasePlayer

    -
    public BasePlayer()
    +
    protected BasePlayer()
  • @@ -780,11 +821,12 @@ implements
    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 @@ implements - - - @@ -928,14 +952,59 @@ public final  + + + + + + + + + + +
    @@ -954,18 +1023,60 @@ public final 
  • previous

    -
    public final void previous()
    -
    +
    @Deprecated
    +public final void previous()
    +
    Deprecated.
    +
    +
    Specified by:
    +
    previous in interface Player
    +
    +
  • + + + + + + + + + @@ -975,8 +1086,23 @@ public final 
  • hasNext

    -
    public final boolean hasNext()
    -
    +
    @Deprecated
    +public final boolean hasNext()
    +
    Deprecated.
    +
    +
    Specified by:
    +
    hasNext in interface Player
    +
    +
  • + + + + + @@ -995,17 +1121,56 @@ public final 
  • next

    -
    public final void next()
    -
    +
    @Deprecated
    +public final void next()
    +
    Deprecated.
    +
    +
    Specified by:
    +
    next in interface Player
    +
    +
  • + + + + + + + + + @@ -1061,8 +1226,8 @@ public final 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 @@ public final public final int getPreviousWindowIndex()

    -
    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 @@ public final  - - -

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

    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 15fd370cd3..98a6bf450f 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 @@ implements protected ExoPlaybackException -createRendererException​(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 @@ implements protected ExoPlaybackException -createRendererException​(Throwable cause, +createRendererException​(Throwable cause, Format format, - boolean isRecoverable) + int errorCode)
    Creates an ExoPlaybackException of type ExoPlaybackException.TYPE_RENDERER for this renderer.
    @@ -317,8 +319,7 @@ implements 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.
    @@ -352,7 +353,7 @@ implements void handleMessage​(int messageType, - Object payload) + Object message)
    Handles a message delivered to the target.
    @@ -565,8 +566,8 @@ implements 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 @@ public 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 @@ public final public final boolean hasReadStreamToEnd()
    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 @@ public final public final 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.

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

    @@ -823,9 +821,8 @@ public final 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 @@ public final 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 @@ public final 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 @@ public final public final void disable()
    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 @@ public int 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 @@ public int supportsMixedMimeTypeAdaptation()
    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 @@ public int supportsMixedMimeTypeAdaptation()
    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 @@ public int supportsMixedMimeTypeAdaptation()

    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,25 +1170,7 @@ public int supportsMixedMimeTypeAdaptation()

    - - - - - + + + + +
      +
    • +

      createRendererException

      +
      protected final ExoPlaybackException createRendererException​(Throwable cause,
      +                                                             @Nullable
      +                                                             Format format,
      +                                                             boolean isRecoverable,
      +                                                             @ErrorCode
      +                                                             int errorCode)
      Creates an ExoPlaybackException of type ExoPlaybackException.TYPE_RENDERER for this renderer.
      @@ -1211,6 +1214,10 @@ public int supportsMixedMimeTypeAdaptation()
      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 9958edb4f2..604d17d291 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 ac5f3b8df9..cf3775891d 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) - - - - - + + + + + - - + +

  • -
    public class DefaultControlDispatcher
    +
    @Deprecated
    +public class DefaultControlDispatcher
     extends Object
     implements ControlDispatcher
    - +
    Deprecated. +
    Use a ForwardingPlayer or configure the player to customize operations.
    +
    Creates an instance with the given increments.
    Parameters:
    @@ -456,6 +390,7 @@ implements

    dispatchPrepare

    public boolean dispatchPrepare​(Player player)
    +
    Deprecated.
    Description copied from interface: ControlDispatcher
    Dispatches a Player.prepare() operation.
    @@ -476,6 +411,7 @@ implements public boolean dispatchSetPlayWhenReady​(Player player, boolean playWhenReady)
    +
    Deprecated.
    Description copied from interface: ControlDispatcher
    Dispatches a Player.setPlayWhenReady(boolean) operation.
    @@ -498,6 +434,7 @@ implements public boolean dispatchSeekTo​(Player player, int windowIndex, long positionMs) +
    Deprecated.
    Description copied from interface: ControlDispatcher
    Dispatches a Player.seekTo(int, long) operation.
    @@ -520,8 +457,9 @@ implements

    dispatchPrevious

    public boolean dispatchPrevious​(Player player)
    +
    Deprecated.
    Description copied from interface: ControlDispatcher
    -
    Dispatches a Player.previous() operation.
    +
    Dispatches a Player.seekToPreviousWindow() operation.
    Specified by:
    dispatchPrevious in interface ControlDispatcher
    @@ -539,8 +477,9 @@ implements

    dispatchNext

    public boolean dispatchNext​(Player player)
    +
    Deprecated.
    Description copied from interface: ControlDispatcher
    -
    Dispatches a Player.next() operation.
    +
    Dispatches a Player.seekToNextWindow() operation.
    Specified by:
    dispatchNext in interface ControlDispatcher
    @@ -558,6 +497,7 @@ implements

    dispatchRewind

    public boolean dispatchRewind​(Player player)
    +
    Deprecated.
    Description copied from interface: ControlDispatcher
    Dispatches a rewind operation.
    @@ -577,6 +517,7 @@ implements

    dispatchFastForward

    public boolean dispatchFastForward​(Player player)
    +
    Deprecated.
    Description copied from interface: ControlDispatcher
    Dispatches a fast forward operation.
    @@ -598,6 +539,7 @@ implements public boolean dispatchSetRepeatMode​(Player player, @RepeatMode int repeatMode) +
    Deprecated.
    Description copied from interface: ControlDispatcher
    Dispatches a Player.setRepeatMode(int) operation.
    @@ -619,6 +561,7 @@ implements public boolean dispatchSetShuffleModeEnabled​(Player player, boolean shuffleModeEnabled) +
    Deprecated.
    Description copied from interface: ControlDispatcher
    @@ -640,6 +583,7 @@ implements public boolean dispatchStop​(Player player, boolean reset) +
    Deprecated.
    Description copied from interface: ControlDispatcher
    Dispatches a Player.stop() operation.
    @@ -661,6 +605,7 @@ implements public boolean dispatchSetPlaybackParameters​(Player player, PlaybackParameters playbackParameters) +
    Deprecated.
    Description copied from interface: ControlDispatcher
    @@ -681,6 +626,7 @@ implements

    isRewindEnabled

    public boolean isRewindEnabled()
    +
    Deprecated.
    Returns true if rewind is enabled, false otherwise.
    @@ -696,6 +642,7 @@ implements

    isFastForwardEnabled

    public boolean isFastForwardEnabled()
    +
    Deprecated.
    Returns true if fast forward is enabled, false otherwise.
    @@ -704,52 +651,26 @@ implements +
    • getRewindIncrementMs

      -
      public long getRewindIncrementMs()
      +
      public long getRewindIncrementMs​(Player player)
      +
      Deprecated.
      Returns the rewind increment in milliseconds.
    - - - -
      -
    • -

      getFastForwardIncrementMs

      -
      public long getFastForwardIncrementMs()
      -
      Returns the fast forward increment in milliseconds.
      -
    • -
    - - - -
      -
    • -

      setRewindIncrementMs

      -
      @Deprecated
      -public void setRewindIncrementMs​(long 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.
      -
      -
    • -
    - +
    • -

      setFastForwardIncrementMs

      -
      @Deprecated
      -public void setFastForwardIncrementMs​(long fastForwardMs)
      -
      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.
      -
      +

      getFastForwardIncrementMs

      +
      public long getFastForwardIncrementMs​(Player player)
      +
      Deprecated.
      +
      Returns the fast forward increment in milliseconds.
    @@ -804,13 +725,13 @@ public void setFastForwardIncrementMs​(long fastForwardMs)< diff --git a/docs/doc/reference/com/google/android/exoplayer2/DefaultRenderersFactory.html b/docs/doc/reference/com/google/android/exoplayer2/DefaultRenderersFactory.html index 14ddddb3e9..26c599093b 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/DefaultRenderersFactory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/DefaultRenderersFactory.html @@ -501,8 +501,8 @@ implements Allow use of extension renderers. Extension renderers are indexed after core renderers of the same type. A 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.
    See Also:
    Constant Field Values
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ExoPlaybackException.html b/docs/doc/reference/com/google/android/exoplayer2/ExoPlaybackException.html index 8ce46ed0d6..574f40cefb 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ExoPlaybackException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ExoPlaybackException.html @@ -25,8 +25,8 @@ catch(err) { } //--> -var data = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9,"i5":9,"i6":10,"i7":10,"i8":10,"i9":10}; -var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; +var data = {"i0":9,"i1":9,"i2":9,"i3":41,"i4":9,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10}; +var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -127,6 +127,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • java.lang.Exception
  • + +
    • @@ -144,8 +149,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    public final class ExoPlaybackException
    -extends Exception
    -implements Bundleable
    +extends PlaybackException
    Thrown when a non locally recoverable playback failure occurs.
    See Also:
    @@ -180,6 +184,13 @@ implements +
  • + + +

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

    +PlaybackException.ErrorCode, PlaybackException.FieldNumber
  • + + @@ -302,7 +312,7 @@ implements -All Methods Static Methods Instance Methods Concrete Methods  +All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods  Modifier and Type Method @@ -317,48 +327,50 @@ implements static ExoPlaybackException -createForRenderer​(Exception cause) - -
    Creates an instance of type TYPE_RENDERER for an unknown renderer.
    - - - -static ExoPlaybackException -createForRenderer​(Throwable cause, - String rendererName, - int rendererIndex, - Format rendererFormat, - int rendererFormatSupport) - -
    Creates an instance of type TYPE_RENDERER.
    - - - -static ExoPlaybackException -createForRenderer​(Throwable cause, +createForRenderer​(Throwable cause, String rendererName, int rendererIndex, Format rendererFormat, int rendererFormatSupport, - boolean isRecoverable) + boolean isRecoverable, + int errorCode)
    Creates an instance of type TYPE_RENDERER.
    - + static ExoPlaybackException -createForSource​(IOException cause) +createForSource​(IOException cause, + int errorCode)
    Creates an instance of type TYPE_SOURCE.
    - + static ExoPlaybackException createForUnexpected​(RuntimeException cause) + + + + +static ExoPlaybackException +createForUnexpected​(RuntimeException cause, + int errorCode) +
    Creates an instance of type TYPE_UNEXPECTED.
    + +boolean +errorInfoEquals​(PlaybackException that) + +
    Returns whether the error data associated to this exception equals the error data associated to + other.
    + + Exception getRendererException() @@ -389,6 +401,13 @@ implements +
  • + + +

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

    +getErrorCodeName, getErrorCodeName, keyForField
  • + + @@ -512,7 +530,7 @@ public final 

    rendererIndex

    public final int rendererIndex
    -
    If type is TYPE_RENDERER, this is the index of the renderer, or C.INDEX_UNSET if unknown.
    +
    If type is TYPE_RENDERER, this is the index of the renderer.
    @@ -539,16 +557,6 @@ public final int rendererFormatSupport renderer for rendererFormat. If rendererFormat is null, this is C.FORMAT_HANDLED. - - - - @@ -580,66 +588,25 @@ public final  + - - - -
      -
    • -

      createForRenderer

      -
      public static ExoPlaybackException createForRenderer​(Exception cause)
      -
      Creates an instance of type TYPE_RENDERER for an unknown renderer.
      -
      -
      Parameters:
      -
      cause - The cause of the failure.
      -
      Returns:
      -
      The created instance.
      -
      -
    • -
    - - - -
      -
    • -

      createForRenderer

      -
      public static ExoPlaybackException createForRenderer​(Throwable cause,
      -                                                     String rendererName,
      -                                                     int rendererIndex,
      -                                                     @Nullable
      -                                                     Format rendererFormat,
      -                                                     @FormatSupport
      -                                                     int rendererFormatSupport)
      -
      Creates an instance of type TYPE_RENDERER.
      -
      -
      Parameters:
      -
      cause - The cause of the failure.
      -
      rendererIndex - The index of the renderer in which the failure occurred.
      -
      rendererFormat - The Format the renderer was using at the time of the exception, - or null if the renderer wasn't using a Format.
      -
      rendererFormatSupport - The C.FormatSupport of the renderer for - rendererFormat. Ignored if rendererFormat is null.
      -
      Returns:
      -
      The created instance.
      -
      -
    • -
    - + + + + +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ExoPlayer.Builder.html b/docs/doc/reference/com/google/android/exoplayer2/ExoPlayer.Builder.html index 5939295229..f305d7cffe 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ExoPlayer.Builder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ExoPlayer.Builder.html @@ -416,7 +416,7 @@ extends Deprecated.
    Set a limit on the time a call to ExoPlayer.setForegroundMode(boolean) can spend. If a call to ExoPlayer.setForegroundMode(boolean) takes more than timeoutMs milliseconds to - complete, the player will raise an error via Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException). + complete, the player will raise an error via Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException).

    This method is experimental, and will be renamed or removed in a future release.

    @@ -593,7 +593,7 @@ extends Sets a timeout for calls to Player.release() and ExoPlayer.setForegroundMode(boolean).

    If a call to Player.release() or ExoPlayer.setForegroundMode(boolean) takes more than - timeoutMs to complete, the player will report an error via Player.Listener.onPlayerError(com.google.android.exoplayer2.ExoPlaybackException). + timeoutMs to complete, the player will report an error via Player.Listener.onPlayerError(com.google.android.exoplayer2.PlaybackException).

    Parameters:
    releaseTimeoutMs - The release timeout, in milliseconds.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ExoPlayer.html b/docs/doc/reference/com/google/android/exoplayer2/ExoPlayer.html index 27f9e8c34f..e8a5fbd7ea 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ExoPlayer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ExoPlayer.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,"i15":6,"i16":6,"i17":6,"i18":6,"i19":6,"i20":38,"i21":38,"i22":6,"i23":38,"i24":6,"i25":6,"i26":6,"i27":6,"i28":6,"i29":6,"i30":6,"i31":6,"i32":6,"i33":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,"i16":6,"i17":6,"i18":6,"i19":6,"i20":6,"i21":38,"i22":38,"i23":6,"i24":38,"i25":6,"i26":6,"i27":6,"i28":6,"i29":6,"i30":6,"i31":6,"i32":6,"i33":6,"i34":6}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -133,7 +133,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); extends Player
    An extensible media player that plays MediaSources. Instances can be obtained from 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 @@ -173,7 +173,7 @@ extends 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. @@ -282,7 +282,7 @@ extends

    Nested classes/interfaces inherited from interface com.google.android.exoplayer2.Player

    -Player.Command, Player.Commands, Player.DiscontinuityReason, Player.EventFlags, Player.EventListener, Player.Events, Player.Listener, Player.MediaItemTransitionReason, Player.PlaybackSuppressionReason, Player.PlayWhenReadyChangeReason, Player.PositionInfo, Player.RepeatMode, Player.State, Player.TimelineChangeReason +Player.Command, Player.Commands, Player.DiscontinuityReason, Player.Event, Player.EventListener, Player.Events, Player.Listener, Player.MediaItemTransitionReason, Player.PlaybackSuppressionReason, Player.PlayWhenReadyChangeReason, Player.PositionInfo, Player.RepeatMode, Player.State, Player.TimelineChangeReason @@ -315,7 +315,7 @@ extends

    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 @@ -435,48 +435,56 @@ extends +ExoPlaybackException +getPlayerError() + +
    Equivalent to Player.getPlayerError(), except the exception is guaranteed to be an + ExoPlaybackException.
    + + + int getRendererCount()
    Returns the number of renderers.
    - + int getRendererType​(int index)
    Returns the track type that the renderer at a given index handles.
    - + SeekParameters getSeekParameters()
    Returns the currently active SeekParameters of the player.
    - + ExoPlayer.TextComponent getTextComponent()
    Returns the component of this player for text output, or null if text is not supported.
    - + TrackSelector getTrackSelector()
    Returns the track selector that this player uses, or null if track selection is not supported.
    - + ExoPlayer.VideoComponent getVideoComponent()
    Returns the component of this player for video output, or null if video is not supported.
    - + void prepare​(MediaSource mediaSource) @@ -485,7 +493,7 @@ extends - + void prepare​(MediaSource mediaSource, boolean resetPosition, @@ -496,14 +504,14 @@ extends - + void removeAudioOffloadListener​(ExoPlayer.AudioOffloadListener listener)
    Removes a listener of audio offload events.
    - + void retry() @@ -512,7 +520,7 @@ extends - + void setForegroundMode​(boolean foregroundMode) @@ -520,7 +528,7 @@ extends - + void setMediaSource​(MediaSource mediaSource) @@ -528,7 +536,7 @@ extends - + void setMediaSource​(MediaSource mediaSource, boolean resetPosition) @@ -536,7 +544,7 @@ extends Clears the playlist and adds the specified MediaSource.
    - + void setMediaSource​(MediaSource mediaSource, long startPositionMs) @@ -544,7 +552,7 @@ extends Clears the playlist and adds the specified MediaSource. - + void setMediaSources​(List<MediaSource> mediaSources) @@ -552,7 +560,7 @@ extends - + void setMediaSources​(List<MediaSource> mediaSources, boolean resetPosition) @@ -560,7 +568,7 @@ extends Clears the playlist and adds the specified MediaSources. - + void setMediaSources​(List<MediaSource> mediaSources, int startWindowIndex, @@ -569,21 +577,21 @@ extends Clears the playlist and adds the specified MediaSources. - + void setPauseAtEndOfMediaItems​(boolean pauseAtEndOfMediaItems)
    Sets whether to pause playback at the end of each media item.
    - + void setSeekParameters​(SeekParameters seekParameters)
    Sets the parameters that control how seek operations are performed.
    - + void setShuffleOrder​(ShuffleOrder shuffleOrder) @@ -596,7 +604,7 @@ extends

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

    -addListener, addListener, addMediaItem, addMediaItem, addMediaItems, addMediaItems, clearMediaItems, clearVideoSurface, clearVideoSurface, clearVideoSurfaceHolder, clearVideoSurfaceView, clearVideoTextureView, decreaseDeviceVolume, getApplicationLooper, getAudioAttributes, getAvailableCommands, getBufferedPercentage, getBufferedPosition, getContentBufferedPosition, getContentDuration, getContentPosition, getCurrentAdGroupIndex, getCurrentAdIndexInAdGroup, getCurrentCues, getCurrentLiveOffset, getCurrentManifest, getCurrentMediaItem, getCurrentPeriodIndex, getCurrentPosition, getCurrentStaticMetadata, getCurrentTag, getCurrentTimeline, getCurrentTrackGroups, getCurrentTrackSelections, getCurrentWindowIndex, getDeviceInfo, getDeviceVolume, getDuration, getMediaItemAt, getMediaItemCount, getMediaMetadata, getNextWindowIndex, getPlaybackError, getPlaybackParameters, getPlaybackState, getPlaybackSuppressionReason, getPlayerError, getPlayWhenReady, getPreviousWindowIndex, getRepeatMode, getShuffleModeEnabled, getTotalBufferedDuration, getVideoSize, getVolume, hasNext, hasPrevious, increaseDeviceVolume, isCommandAvailable, isCurrentWindowDynamic, isCurrentWindowLive, isCurrentWindowSeekable, isDeviceMuted, isLoading, isPlaying, isPlayingAd, moveMediaItem, moveMediaItems, next, pause, play, prepare, previous, release, removeListener, removeListener, removeMediaItem, removeMediaItems, seekTo, seekTo, seekToDefaultPosition, seekToDefaultPosition, setDeviceMuted, setDeviceVolume, setMediaItem, setMediaItem, setMediaItem, setMediaItems, setMediaItems, setMediaItems, setPlaybackParameters, setPlaybackSpeed, setPlayWhenReady, setRepeatMode, setShuffleModeEnabled, setVideoSurface, setVideoSurfaceHolder, setVideoSurfaceView, setVideoTextureView, setVolume, stop, stop +addListener, addListener, addMediaItem, addMediaItem, addMediaItems, addMediaItems, clearMediaItems, clearVideoSurface, clearVideoSurface, clearVideoSurfaceHolder, clearVideoSurfaceView, clearVideoTextureView, decreaseDeviceVolume, getApplicationLooper, getAudioAttributes, getAvailableCommands, getBufferedPercentage, getBufferedPosition, getContentBufferedPosition, getContentDuration, getContentPosition, getCurrentAdGroupIndex, getCurrentAdIndexInAdGroup, getCurrentCues, getCurrentLiveOffset, getCurrentManifest, getCurrentMediaItem, getCurrentPeriodIndex, getCurrentPosition, getCurrentStaticMetadata, getCurrentTimeline, getCurrentTrackGroups, getCurrentTrackSelections, getCurrentWindowIndex, getDeviceInfo, getDeviceVolume, getDuration, getMaxSeekToPreviousPosition, getMediaItemAt, getMediaItemCount, getMediaMetadata, getNextWindowIndex, getPlaybackParameters, getPlaybackState, getPlaybackSuppressionReason, getPlaylistMetadata, getPlayWhenReady, getPreviousWindowIndex, getRepeatMode, getSeekBackIncrement, getSeekForwardIncrement, getShuffleModeEnabled, getTotalBufferedDuration, getVideoSize, getVolume, hasNext, hasNextWindow, hasPrevious, hasPreviousWindow, increaseDeviceVolume, isCommandAvailable, isCurrentWindowDynamic, isCurrentWindowLive, isCurrentWindowSeekable, isDeviceMuted, isLoading, isPlaying, isPlayingAd, moveMediaItem, moveMediaItems, next, pause, play, prepare, previous, release, removeListener, removeListener, removeMediaItem, removeMediaItems, seekBack, seekForward, seekTo, seekTo, seekToDefaultPosition, seekToDefaultPosition, seekToNext, seekToNextWindow, seekToPrevious, seekToPreviousWindow, setDeviceMuted, setDeviceVolume, setMediaItem, setMediaItem, setMediaItem, setMediaItems, setMediaItems, setMediaItems, setPlaybackParameters, setPlaybackSpeed, setPlaylistMetadata, setPlayWhenReady, setRepeatMode, setShuffleModeEnabled, setVideoSurface, setVideoSurfaceHolder, setVideoSurfaceView, setVideoTextureView, setVolume, stop, stop @@ -639,6 +647,25 @@ extends

    Method Detail

    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/ExoTimeoutException.html b/docs/doc/reference/com/google/android/exoplayer2/ExoTimeoutException.html index 0c9ff8457e..a0269f4863 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ExoTimeoutException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ExoTimeoutException.html @@ -121,6 +121,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • java.lang.Exception
    • +
    • java.lang.RuntimeException
    • +
    • +
      • com.google.android.exoplayer2.ExoTimeoutException
    • @@ -129,6 +132,8 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • + +
    • @@ -138,7 +143,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    public final class ExoTimeoutException
    -extends Exception
    +extends RuntimeException
    A timeout of an operation on the ExoPlayer playback thread.
    See Also:
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/Format.html b/docs/doc/reference/com/google/android/exoplayer2/Format.html index e3e740d261..9e78b8eb59 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/Format.html +++ b/docs/doc/reference/com/google/android/exoplayer2/Format.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":10,"i1":42,"i2":42,"i3":10,"i4":42,"i5":42,"i6":42,"i7":42,"i8":42,"i9":42,"i10":42,"i11":42,"i12":41,"i13":41,"i14":41,"i15":41,"i16":41,"i17":41,"i18":41,"i19":41,"i20":41,"i21":41,"i22":41,"i23":41,"i24":41,"i25":41,"i26":41,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":9,"i33":10,"i34":10,"i35":10}; +var data = {"i0":10,"i1":42,"i2":42,"i3":10,"i4":42,"i5":42,"i6":42,"i7":42,"i8":42,"i9":42,"i10":42,"i11":42,"i12":41,"i13":41,"i14":41,"i15":41,"i16":41,"i17":41,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":9,"i24":10,"i25":10,"i26":10}; var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"],32:["t6","Deprecated Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -141,7 +141,7 @@ implements Supported formats page. -

    Fields commonly relevant to all formats

    +

    Fields commonly relevant to all formats

    -

    Fields relevant to container formats

    +

    Fields relevant to container formats

    -

    Fields relevant to sample formats

    +

    Fields relevant to sample formats

    -

    Fields relevant to video formats

    +

    Fields relevant to video formats

    -

    Fields relevant to audio formats

    +

    Fields relevant to audio formats

    -

    Fields relevant to text formats

    +

    Fields relevant to text formats

    @@ -1391,40 +1228,6 @@ public final  - - -
      -
    • -

      createVideoContainerFormat

      -
      @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<byte[]> initializationData,
      -                                                @SelectionFlags
      -                                                int selectionFlags,
      -                                                @RoleFlags
      -                                                int roleFlags)
      -
      Deprecated. - -
      -
    • -
    @@ -1481,76 +1284,6 @@ public static  - - -
      -
    • -

      createVideoSampleFormat

      -
      @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<byte[]> initializationData,
      -                                             int rotationDegrees,
      -                                             float pixelWidthHeightRatio,
      -                                             @Nullable
      -                                             byte[] projectionData,
      -                                             @StereoMode
      -                                             int stereoMode,
      -                                             @Nullable
      -                                             ColorInfo colorInfo,
      -                                             @Nullable
      -                                             DrmInitData drmInitData)
      -
      Deprecated. - -
      -
    • -
    - - - -
      -
    • -

      createAudioContainerFormat

      -
      @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<byte[]> initializationData,
      -                                                @SelectionFlags
      -                                                int selectionFlags,
      -                                                @RoleFlags
      -                                                int roleFlags,
      -                                                @Nullable
      -                                                String language)
      -
      Deprecated. - -
      -
    • -
    @@ -1613,167 +1346,6 @@ public static  - - -
      -
    • -

      createAudioSampleFormat

      -
      @Deprecated
      -public static Format createAudioSampleFormat​(@Nullable
      -                                             String id,
      -                                             @Nullable
      -                                             String sampleMimeType,
      -                                             @Nullable
      -                                             String codecs,
      -                                             int bitrate,
      -                                             int maxInputSize,
      -                                             int channelCount,
      -                                             int sampleRate,
      -                                             @PcmEncoding
      -                                             int pcmEncoding,
      -                                             int encoderDelay,
      -                                             int encoderPadding,
      -                                             @Nullable
      -                                             List<byte[]> initializationData,
      -                                             @Nullable
      -                                             DrmInitData drmInitData,
      -                                             @SelectionFlags
      -                                             int selectionFlags,
      -                                             @Nullable
      -                                             String language,
      -                                             @Nullable
      -                                             Metadata metadata)
      -
      Deprecated. - -
      -
    • -
    - - - - - - - - - - - - - - - -
      -
    • -

      createTextSampleFormat

      -
      @Deprecated
      -public static Format createTextSampleFormat​(@Nullable
      -                                            String id,
      -                                            @Nullable
      -                                            String sampleMimeType,
      -                                            @SelectionFlags
      -                                            int selectionFlags,
      -                                            @Nullable
      -                                            String language,
      -                                            int accessibilityChannel,
      -                                            long subsampleOffsetUs,
      -                                            @Nullable
      -                                            List<byte[]> initializationData)
      -
      Deprecated. - -
      -
    • -
    - - - - diff --git a/docs/doc/reference/com/google/android/exoplayer2/ForwardingPlayer.html b/docs/doc/reference/com/google/android/exoplayer2/ForwardingPlayer.html new file mode 100644 index 0000000000..ec8d4c572d --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/ForwardingPlayer.html @@ -0,0 +1,3219 @@ + + + + +ForwardingPlayer (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class ForwardingPlayer

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      Player
      +
      +
      +
      public class ForwardingPlayer
      +extends Object
      +implements Player
      +
      A Player that forwards operations to another Player. Applications can use this + class to suppress or modify specific operations, by overriding the respective methods.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        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 06057b42ff..9e476679f9 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 @@ implements +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 @@ implements + + + 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 a081e3e4ee..cceffedcbf 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 @@ extends

    Method Summary

    - + @@ -186,142 +186,254 @@ extends + + + + + - + - + - + - + - + - + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + - + - + - + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + - + - + - + + + + + +
    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 @@ extends
  • setArtworkData

    -
    public MediaMetadata.Builder setArtworkData​(@Nullable
    +
    @Deprecated
    +public MediaMetadata.Builder setArtworkData​(@Nullable
                                                 byte[] artworkData)
    -
    Sets the artwork data as a compressed byte array.
    + +
  • + + + + + + + + + @@ -551,9 +695,163 @@ extends
  • setYear

    -
    public MediaMetadata.Builder setYear​(@Nullable
    +
    @Deprecated
    +public MediaMetadata.Builder setYear​(@Nullable
                                          Integer year)
    -
    Sets the year.
    +
    Deprecated. + +
    +
  • + + + + +
      +
    • +

      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 5e34c93ac3..8aa35d1a6e 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 @@ loadScripts(document, 'script');
    @@ -114,80 +106,20 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    -

    Interface PlaybackPreparer

    +

    Annotation Type MediaMetadata.PictureType

    -
    -
    - -
    -
    -
    @@ -236,16 +168,14 @@ void preparePlayback()
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.html b/docs/doc/reference/com/google/android/exoplayer2/MediaMetadata.html index 050176afb4..a8ce3ba8e0 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 @@ implements The folder type of the media item.
    + +static interface  +MediaMetadata.PictureType + +
    The picture type of the artwork.
    + + + + + + @@ -744,9 +1262,163 @@ public final 
  • year

    -
    @Nullable
    +
    @Deprecated
    +@Nullable
     public final Integer year
    -
    Optional year.
    +
    Deprecated. +
    Use recordingYear instead.
    +
    +
  • + + + + +
      +
    • +

      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 2155cf2b7d..36998fa580 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 @@ implements 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 @@ implements void -handleMessage​(int what, - Object object) +handleMessage​(int messageType, + Object message)
    Handles a message delivered to the target.
    @@ -668,9 +667,8 @@ public 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 @@ public final public final boolean hasReadStreamToEnd()
    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 @@ public final public 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.

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

    @@ -770,9 +766,8 @@ public final 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 @@ public final 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 @@ public final 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 @@ public final public final void disable()
    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 @@ public final 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
    @@ -996,9 +987,9 @@ public int 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 @@ public int supportsMixedMimeTypeAdaptation()
      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 @@ public int supportsMixedMimeTypeAdaptation()
      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 @@ public int supportsMixedMimeTypeAdaptation()
      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 @@ public int supportsMixedMimeTypeAdaptation()
      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 @@ public int supportsMixedMimeTypeAdaptation()
      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 @@ public int supportsMixedMimeTypeAdaptation()

      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 76298e016a..32fab39457 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 @@ loadScripts(document, 'script'); @@ -159,6 +165,38 @@ extends
    + + + +
      +
    • +

      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 4163538cb5..51e7f50293 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 3b920c7f43..45d4c5a057 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ implements Single media file or on-demand stream
    + 

    Single media file or on-demand stream

    Example timeline for a
  single file @@ -171,7 +171,7 @@ implements Example timeline for a
  playlist of files @@ -182,7 +182,7 @@ implements Live stream with limited availability +

    Live stream with limited availability

    Example timeline for
  a live stream with limited availability @@ -195,7 +195,7 @@ implements Example timeline
  for a live stream with indefinite availability @@ -204,7 +204,7 @@ implements Live stream with multiple periods +

    Live stream with multiple periods

    Example timeline
  for a live stream with multiple periods @@ -214,7 +214,7 @@ implements Example timeline for an
  on-demand stream followed by a live stream @@ -224,7 +224,7 @@ implements 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 @@ implements 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 @@ implements -All Methods Instance Methods Abstract Methods Concrete Methods Deprecated Methods  +All Methods Instance Methods Abstract Methods Concrete Methods  Modifier and Type Method @@ -473,17 +480,6 @@ implements -Timeline.Window -getWindow​(int windowIndex, - Timeline.Window window, - boolean setTag) - -
    Deprecated. - -
    - - - abstract Timeline.Window getWindow​(int windowIndex, Timeline.Window window, @@ -492,26 +488,26 @@ implements 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 @@ implements + Bundle toBundle()
    Returns a Bundle representing the information stored in this object.
    + +Bundle +toBundle​(boolean excludeMediaItems) +
    adjusts its state and position to the seek. - - - -
      -
    • -

      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 @@ public void release()

    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 @@ public void release()

    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 @@ public void release()

    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 @@ public void release()

    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 @@ public void release()
    • 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 @@ public void release()
    + + + + @@ -1757,7 +1782,7 @@ public void release()
  • 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 @@ public void release()
    Specified by:
    onPlaybackStateChanged in interface Player.Listener
    Parameters:
    -
    state - The new playback state.
    +
    playbackState - The new playback state.
  • @@ -1888,24 +1913,27 @@ public void release()
    - +
    + + + + + + + + + + + + @@ -1978,8 +2071,8 @@ public void release()
    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 @@ public void release()
    + + + + + + + + @@ -2013,8 +2142,8 @@ public void release()
  • 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 @@ public void release()
    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 @@ public void release()

    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 ba491abe23..1dc95dc465 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 @@ extends Description -Events​(ExoFlags flags, +Events​(FlagSet flags, SparseArray<AnalyticsListener.EventTime> eventTimes)
    Creates an instance.
    @@ -239,18 +239,18 @@ extends

    Constructor Detail

    - +
    + + + + + + + + + + + + + + + + @@ -2205,6 +2360,55 @@ default void onSeekProcessed​( + + +
      +
    • +

      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 @@ default void 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.
      +
      +
    • +
    + @@ -2337,7 +2551,8 @@ default void onLoadingChanged​(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.Listener.onStaticMetadataChanged(List) and MetadataOutput.onMetadata(Metadata). + and the static and dynamic metadata from the track + selections' formats and MetadataOutput.onMetadata(Metadata).

    Parameters:
    eventTime - The event time.
    @@ -2345,6 +2560,22 @@ default void onLoadingChanged​( + + + @@ -2415,7 +2646,7 @@ default void onLoadingChanged​(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 @@ default void 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 @@ default void onAudioInputFormatChanged​(

    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 @@ default void onAudioInputFormatChanged​(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 @@ default void onAudioInputFormatChanged​(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 @@ default void onAudioInputFormatChanged​(

    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 @@ default void onVideoInputFormatChanged​(

    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 @@ default void onVideoInputFormatChanged​(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 @@ default void onDrmSessionAcquired​(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 037acf1a8c..f2a47b0391 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 @@ implements 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 @@ implements void onAdPlaybackStarted​(AnalyticsListener.EventTime eventTime, - String contentSession, - String adSession) + String contentSessionId, + String adSessionId)
    Called when a session is interrupted by ad playback.
    @@ -318,8 +318,8 @@ implements 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 @@ implements void onSessionActive​(AnalyticsListener.EventTime eventTime, - String session) + String sessionId)
    Called when a session becomes active, i.e.
    @@ -336,7 +336,7 @@ implements void onSessionCreated​(AnalyticsListener.EventTime eventTime, - String session) + String sessionId)
    Called when a new session is created as a result of PlaybackSessionManager.updateSessions(EventTime).
    @@ -344,8 +344,8 @@ implements void onSessionFinished​(AnalyticsListener.EventTime eventTime, - String session, - boolean automaticTransition) + String sessionId, + boolean automaticTransitionToNextPlayback)
    Called when a session is permanently finished.
    @@ -372,7 +372,7 @@ implements 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 @@ public 

    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 @@ public 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 @@ public 

    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 @@ public 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 @@ public 

    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 @@ public 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 @@ public 

    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 @@ public 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 @@ public 

    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 @@ public 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 @@ public 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 @@ public 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 59f23c34a5..02a56bf85c 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 @@ extends static String -E_AC_3_CODEC_STRING +E_AC3_JOC_CODEC_STRING -
    A non-standard codec string for E-AC-3.
    +
    A non-standard codec string for E-AC3-JOC.
    @@ -328,20 +328,20 @@ extends

    Field Detail

    - +
    • -

      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 cfc52d28dc..9e70641448 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 @@ extends 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 68cdfdb6f1..eecefafcb3 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); void -queueInput​(ByteBuffer buffer) +queueInput​(ByteBuffer inputBuffer)
    Queues audio data between the position and limit of the input buffer for processing.
    @@ -344,7 +344,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); previous buffer returned by getOutput().
      Parameters:
      -
      buffer - The input buffer to process.
      +
      inputBuffer - The input buffer to process.
    @@ -363,11 +363,10 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 8b7454693e..ac7f66f0c9 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 @@ default void onAudioInputFormatChanged​(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 @@ default void onAudioInputFormatChanged​(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 a48843218b..fcd9bbc413 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 b31f611ddd..75df441db5 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 @@ extends 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 dc2f7c59f1..049db6402d 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 @@ int getFormatSupport​(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 faeb9f0f4a..75c47e1b31 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 @@ implements public final void queueEndOfStream() -
    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 ec55870677..88fb36940c 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 @@ implements 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 @@ protected void onPositionDiscontinuity()
      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 @@ protected void onPositionDiscontinuity()
      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 @@ protected void onPositionDiscontinuity()
      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 438f495204..536ea3dffe 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 @@ implements static int +OFFLOAD_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 @@ implements + + +
        +
      • +

        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 @@ implements 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 @@ public int getFormatSupport​(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 ad81dc23be..b4e9d3044a 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 @@ public int getFormatSupport​(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 487dba630d..e05758282c 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 @@ implements 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 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 f5f09e949b..5141097f13 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 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends
    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 @@ extends 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 007f2922a0..2426417422 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 @@ implements 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 b096b30cd1..5378524f58 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 @@ loadScripts(document, 'script'); @@ -159,6 +159,31 @@ extends @@ -193,7 +193,7 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends + 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 @@ extends + long getContentBufferedPosition() @@ -363,7 +353,7 @@ extends + long getContentPosition() @@ -371,7 +361,7 @@ extends + int getCurrentAdGroupIndex() @@ -379,28 +369,28 @@ extends + 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 @@ extends + 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 @@ extends + +int +getMaxSeekToPreviousPosition() + +
    Returns the maximum position for which Player.seekToPrevious() seeks to the previous window, + in milliseconds.
    + + + MediaMetadata getMediaMetadata() @@ -481,21 +479,21 @@ extends + PlaybackParameters getPlaybackParameters()
    Returns the currently active playback parameters.
    - + int getPlaybackState()
    Returns the current playback state of the player.
    - + int getPlaybackSuppressionReason() @@ -503,13 +501,20 @@ extends 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 @@ extends +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 @@ extends 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 @@ extends Removes a range of media items from the playlist. - + void seekTo​(int windowIndex, long positionMs) @@ -682,21 +659,21 @@ extends 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 @@ extends Clears the playlist and adds the specified MediaItems. - + void setMediaItems​(List<MediaItem> mediaItems, int startWindowIndex, @@ -713,77 +690,84 @@ extends 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 @@ extends 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 + + + + + + + +
      +
    • +

      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 3cc3860c38..ed353aae8c 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 @@ implements 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 @@ implements
  • 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 @@ implements
  • 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 84924d24b0..cd11401f07 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 @@ implements 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 @@ implements 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 @@ implements 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 @@ implements + + +
      +
    • +

      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 @@ public final 
  • + + + +
      +
    • +

      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 @@ public final 
  • setFallbackFactory

    -
    public CronetDataSource.Factory setFallbackFactory​(@Nullable
    +
    @Deprecated
    +public CronetDataSource.Factory setFallbackFactory​(@Nullable
                                                        HttpDataSource.Factory fallbackFactory)
    +
    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.
    +
    Sets the fallback HttpDataSource.Factory that is used as a fallback if the CronetEngineWrapper fails to provide a CronetEngine.

    By default a DefaultHttpDataSource is used as fallback factory.

    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.OpenException.html b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.OpenException.html index 936a8396fe..dfdba29ca0 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.OpenException.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/cronet/CronetDataSource.OpenException.html @@ -124,6 +124,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • java.io.IOException
  • @@ -228,15 +240,43 @@ extends 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 @@ extends

    Method Summary

    + + + + + + -
    Description copied from interface: DataReader
    Reads up to length bytes of data from the input. @@ -824,7 +868,7 @@ public 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 7f6c49cb20..b7187d77b8 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 @@ loadScripts(document, 'script');
    @@ -129,8 +123,15 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); @@ -138,84 +139,6 @@ extends
    • - -
      - -
      - -
      -
        -
      • - - -

        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 @@ extends 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 @@ extends

        Method Summary

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

              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 @@ extends

              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 @@ extends 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 @@ extends 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 @@ extends

    CronetEngineWrapper

    public CronetEngineWrapper​(org.chromium.net.CronetEngine cronetEngine)
    +
    Deprecated.
    Creates a wrapper for an existing CronetEngine.
    Parameters:
    @@ -432,31 +266,6 @@ extends
    - -
    - -
    @@ -505,16 +314,16 @@ public int 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 0000000000..ae3a8ee830 --- /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 cf9f6dd956..dd92b5129f 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); CronetEngineWrapper +Deprecated. +
    Use CronetEngine directly.
    + + + +CronetUtil -
    A wrapper class for a CronetEngine.
    +
    Cronet utility methods.
    @@ -147,23 +153,6 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); -
  • - - - - - - - - - - - - -
    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 73483b20ca..d038641cdb 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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)
  • + + + +
      +
    • +

      sameAs

      +
      default boolean sameAs​(android.support.v4.media.MediaMetadataCompat oldMetadata,
      +                       android.support.v4.media.MediaMetadataCompat newMetadata)
      +
      Returns whether the old and the new metadata are considered the same.
      +
    • +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.QueueNavigator.html b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.QueueNavigator.html index bcfd4d900a..907cfdb50d 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.QueueNavigator.html +++ b/docs/doc/reference/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.QueueNavigator.html @@ -352,13 +352,16 @@ extends

    onSkipToPrevious

    void onSkipToPrevious​(Player player,
    +                      @Deprecated
                           ControlDispatcher controlDispatcher)
    See MediaSessionCompat.Callback.onSkipToPrevious().
    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)).
    @@ -369,14 +372,17 @@ extends

    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 @@ extends

    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 240ff9e156..2fbe4eb63f 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 @@ extends 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 @@ extends . - + android.support.v4.media.session.MediaSessionCompat mediaSession @@ -390,7 +383,9 @@ extends void setControlDispatcher​(ControlDispatcher controlDispatcher) - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to setPlayer(Player) instead.
    +
    @@ -426,25 +421,24 @@ extends void +setDispatchUnsupportedActionsEnabled​(boolean dispatchUnsupportedActionsEnabled) + +
    Sets whether actions that are not advertised to the MediaSessionCompat will be + dispatched either way.
    + + + +void setEnabledPlaybackActions​(long enabledPlaybackActions)
    Sets the enabled playback actions.
    - -void -setErrorMessageProvider​(ErrorMessageProvider<? super ExoPlaybackException> errorMessageProvider) - -
    Sets the optional ErrorMessageProvider.
    - - void -setFastForwardIncrementMs​(int fastForwardMs) +setErrorMessageProvider​(ErrorMessageProvider<? super PlaybackException> errorMessageProvider) - +
    Sets the optional ErrorMessageProvider.
    @@ -463,26 +457,34 @@ extends 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 @@ extends 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 @@ extends

    Field Detail

    - - - -
      -
    • -

      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 @@ extends
  • setControlDispatcher

    -
    public void setControlDispatcher​(ControlDispatcher controlDispatcher)
    - -
    -
    Parameters:
    -
    controlDispatcher - The ControlDispatcher.
    -
    +
    @Deprecated
    +public void setControlDispatcher​(ControlDispatcher controlDispatcher)
    +
    Deprecated. +
    Use a ForwardingPlayer and pass it to setPlayer(Player) instead. + You can also customize some operations when configuring the player (for example by using + SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)).
    +
  • @@ -722,32 +702,6 @@ extends - - - - - - - - @@ -755,7 +709,7 @@ public void setFastForwardIncrementMs​(int fastForwardMs)

    setErrorMessageProvider

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

      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 3f4cd71c3a..32ee306748 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 @@ public static final int DEFAULT_REPEAT_TOGGLE_MODES
  • onCustomAction

    public void onCustomAction​(Player player,
    +                           @Deprecated
                                ControlDispatcher controlDispatcher,
                                String action,
                                @Nullable
    @@ -341,8 +342,10 @@ public static final int DEFAULT_REPEAT_TOGGLE_MODES
    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 b77a67cacb..8eeecc7ba5 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 e7e899f10d..d7e91f838e 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 @@ implements 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 @@ implements

    onCommand

    public boolean onCommand​(Player player,
    +                         @Deprecated
                              ControlDispatcher controlDispatcher,
                              String command,
                              @Nullable
    @@ -496,15 +496,16 @@ implements 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 930f99d023..35b6029880 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 @@ implements 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 @@ implements
    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 @@ implements

    onSkipToPrevious

    public void onSkipToPrevious​(Player player,
    +                             @Deprecated
                                  ControlDispatcher controlDispatcher)
    Description copied from interface: MediaSessionConnector.QueueNavigator
    See MediaSessionCompat.Callback.onSkipToPrevious().
    @@ -497,8 +498,10 @@ implements 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 @@ implements

    onSkipToQueueItem

    public void onSkipToQueueItem​(Player player,
    +                              @Deprecated
                                   ControlDispatcher controlDispatcher,
                                   long id)
    Description copied from interface: MediaSessionConnector.QueueNavigator
    @@ -518,8 +522,10 @@ implements 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 @@ implements

    onSkipToNext

    public void onSkipToNext​(Player player,
    +                         @Deprecated
                              ControlDispatcher controlDispatcher)
    Description copied from interface: MediaSessionConnector.QueueNavigator
    See MediaSessionCompat.Callback.onSkipToNext().
    @@ -538,8 +545,10 @@ implements 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 @@ implements

    onCommand

    public boolean onCommand​(Player player,
    +                         @Deprecated
                              ControlDispatcher controlDispatcher,
                              String command,
                              @Nullable
    @@ -558,15 +568,16 @@ implements 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 bb92c438df..2b43dd966c 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 5537fcc790..68fd3ed58c 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 @@ implements int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -598,7 +598,7 @@ public 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 @@ public 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 @@ public 
  • close

    -
    public void close()
    -           throws HttpDataSource.HttpDataSourceException
    +
    public void close()
    Description copied from interface: DataSource
    Closes the source. This method must be called even if the corresponding call to DataSource.open(DataSpec) threw an IOException.
    @@ -640,8 +639,6 @@ public close in interface DataSource
  • Specified by:
    close in interface HttpDataSource
    -
    Throws:
    -
    HttpDataSource.HttpDataSourceException
    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 becbb9c861..3f3066eeab 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 @@ extends 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    - -

    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 57fe4bf285..86edd52298 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 @@ extends -
  • - - -

    Nested classes/interfaces inherited from interface com.google.android.exoplayer2.upstream.DataSource

    -DataSource.Factory
  • - + + + + + + + + + + + + +
    Nested Classes 
    Modifier and TypeClassDescription
    static class RtmpDataSource.Factory + +
    @@ -224,7 +232,7 @@ extends int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -334,7 +342,7 @@ extends 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 @@ extends 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 5b12c976a6..1372689cfd 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    DataSource.Factory

    -
    public final class RtmpDataSourceFactory
    +
    @Deprecated
    +public final class RtmpDataSourceFactory
     extends Object
     implements DataSource.Factory
    - +
    Deprecated. + +
    @@ -158,11 +161,15 @@ implements RtmpDataSourceFactory() -  + +
    Deprecated.
    RtmpDataSourceFactory​(TransferListener listener) -  + +
    Deprecated.
    +  @@ -176,7 +183,7 @@ implements -All Methods Instance Methods Concrete Methods  +All Methods Instance Methods Concrete Methods Deprecated Methods  Modifier and Type Method @@ -186,6 +193,7 @@ implements RtmpDataSource createDataSource() +
    Deprecated.
    Creates a DataSource instance.
    @@ -220,6 +228,7 @@ implements

    RtmpDataSourceFactory

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

    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 0df22e84d5..5fbf1b1b81 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); -RtmpDataSourceFactory +RtmpDataSource.Factory - + + + + +RtmpDataSourceFactory +Deprecated. + 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 033c1f9dd1..32f83f6dc0 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 dc5b6d5552..0ed5d79010 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 @@ extends 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 -
  • 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>) @@ -272,8 +269,7 @@ extends

    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 2da524d393..b91d7d0a20 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 @@ extends 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 @@ public final int cryptoMode
  • 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 01e885ca99..4d059a1a83 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    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 3156c09b10..3b577bb31a 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 @@ extends 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 5b494b4ec8..f288a7c4e8 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 @@ implements void -init​(ExtractorOutput extractorOutput) +init​(ExtractorOutput output)
    Initializes the extractor with an ExtractorOutput.
    @@ -419,14 +419,14 @@ implements
  • init

    -
    public void init​(ExtractorOutput extractorOutput)
    +
    public void init​(ExtractorOutput output)
    Description copied from interface: Extractor
    Initializes the extractor with an ExtractorOutput. Called at most once.
    Specified by:
    init in interface Extractor
    Parameters:
    -
    extractorOutput - An ExtractorOutput to receive extracted data.
    +
    output - An ExtractorOutput to receive extracted data.
  • @@ -478,8 +478,8 @@ implements 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 916ac9db27..f3affabfd9 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 @@ public int read​(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 37ed14e6dc..45e72516a5 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 @@ implements 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 8dc5a79021..31bbfa20b4 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 @@ public int read​(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 3be56f7ce6..8ecb69e1e4 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 @@ int getElementType​(int id) 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 1c696bef1b..c2710b8d64 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 @@ implements 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 @@ public 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 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 c2f1f0f75d..d666de8860 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 @@ implements 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 @@ implements 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 f3656ae342..82ecce5263 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 @@ implements 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 @@ implements 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 02a15a9a2b..1fcd5f502c 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 @@ implements 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 404a363bcc..cb056d2749 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 @@ public static 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 945dfd8908..7ce17f418b 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 @@ implements
    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 3d44f0b914..5a902b3a46 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 @@ implements 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 0a171ac125..97d0748fb5 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 @@ implements 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 f144bdca37..c7ce01df5a 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 @@ implements 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 @@ implements

    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 @@ implements 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 4d7b50c62f..1c131e1269 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 @@ implements 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 78d1ff221a..53bb6b6779 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 @@ implements 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 @@ implements

    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 @@ implements 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 98bd365c20..2fe8201fd4 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 @@ implements 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 89aa3c3e94..1641343070 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 @@ implements 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 @@ implements 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 b34d6d87e5..f5d7d30304 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 @@ implements 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 2805e8dae1..237a09b1e3 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 @@ implements 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 182366731a..693710f1f6 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    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 f61d0ad210..9c18aeae45 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 @@ extends
    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 9ada74d22c..f20854b788 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 @@ implements 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 bc9babb905..0487ffd65e 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); +boolean +needsReconfiguration() + +
    Whether the adapter needs to be reconfigured before it is used.
    + + + void queueInputBuffer​(int index, int offset, @@ -242,7 +249,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    Submit an input buffer for decoding.
    - + void queueSecureInputBuffer​(int index, int offset, @@ -253,14 +260,14 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    Returns the buffer to the MediaCodec.
    - + void releaseOutputBuffer​(int index, long renderTimeStampNs) @@ -277,7 +284,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); it on the output surface. - + void setOnFrameRenderedListener​(MediaCodecAdapter.OnFrameRenderedListener listener, Handler handler) @@ -285,21 +292,21 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ void setParameters​( -
    • @@ -871,21 +855,6 @@ extends - - -
        -
      • -

        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 @@ protected final 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
      @@ -1272,8 +1241,8 @@ protected final protected void onStarted()
      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 @@ protected void resetCodecStateForRelease() 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 @@ protected  - - -
        -
      • -

        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 @@ protected void onProcessedOutputBuffer​(long presentationTi
      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 @@ protected void onProcessedOutputBuffer​(long presentationTi
      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 6093ba6652..964293772d 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
      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 fd33f3e768..f967d4999e 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 @@ implements +boolean +needsReconfiguration() + +
      Whether the adapter needs to be reconfigured before it is used.
      + + + void queueInputBuffer​(int index, int offset, @@ -242,7 +249,7 @@ implements Submit an input buffer for decoding. - + void queueSecureInputBuffer​(int index, int offset, @@ -253,14 +260,14 @@ implements 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 @@ implements Returns the buffer to the MediaCodec. - + void releaseOutputBuffer​(int index, long renderTimeStampNs) @@ -277,7 +284,7 @@ implements + void setOnFrameRenderedListener​(MediaCodecAdapter.OnFrameRenderedListener listener, Handler handler) @@ -285,21 +292,21 @@ implements 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 @@ implements + + + 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 65cc1d75bf..af7bb84d43 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 @@ extends 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 @@ extends

      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.
    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 81a214399f..35e653f10f 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 @@ implements 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 @@ implements + + + 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 21ae44893d..86d3cb8d33 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 @@ implements   +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 @@ implements Metadata.Entry -getWrappedMetadataBytes, getWrappedMetadataFormat, populateMediaMetadata +getWrappedMetadataBytes, getWrappedMetadataFormat @@ -361,6 +368,26 @@ implements + + + 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 0828707bee..85c4291301 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 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends

    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 @@ extends

    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 @@ extends

    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 2f55f5c58c..d79e35774e 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 @@ extends 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 @@ extends 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 @@ extends

    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 @@ extends

    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 fc91999988..c03a3ae252 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 @@ public DefaultDownloaderFactory​(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 8b6b187b21..ac86bc015f 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); Downloader -createDownloader​(DownloadRequest action) +createDownloader​(DownloadRequest request)
    Creates a Downloader to perform the given DownloadRequest.
    @@ -177,11 +177,11 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/ConcatenatingMediaSource.html b/docs/doc/reference/com/google/android/exoplayer2/source/ConcatenatingMediaSource.html index 0edd5421f8..0af0c9cc22 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/ConcatenatingMediaSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/ConcatenatingMediaSource.html @@ -508,13 +508,6 @@ extends Object clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait - @@ -540,8 +533,7 @@ extends MediaSource... mediaSources)
    Parameters:
    -
    mediaSources - The MediaSources to concatenate. It is valid for the same - MediaSource instance to be present more than once in the array.
    +
    mediaSources - The MediaSources to concatenate. It is valid for the same MediaSource instance to be present more than once in the array.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.html b/docs/doc/reference/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.html index e117b74c3b..c88e4910f6 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.html @@ -158,7 +158,7 @@ implements ads configuration, setAdsLoaderProvider(com.google.android.exoplayer2.source.DefaultMediaSourceFactory.AdsLoaderProvider) and setAdViewProvider(com.google.android.exoplayer2.ui.AdViewProvider) need to be called to diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/ForwardingTimeline.html b/docs/doc/reference/com/google/android/exoplayer2/source/ForwardingTimeline.html index 886560de3c..feb29f196e 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/ForwardingTimeline.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/ForwardingTimeline.html @@ -163,7 +163,7 @@ extends Timeline -Timeline.Period, Timeline.Window +Timeline.Period, Timeline.RemotableTimeline, Timeline.Window diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/MaskingMediaSource.PlaceholderTimeline.html b/docs/doc/reference/com/google/android/exoplayer2/source/MaskingMediaSource.PlaceholderTimeline.html index 1cfdfc7191..c676653279 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/MaskingMediaSource.PlaceholderTimeline.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/MaskingMediaSource.PlaceholderTimeline.html @@ -163,7 +163,7 @@ extends Timeline -Timeline.Period, Timeline.Window +Timeline.Period, Timeline.RemotableTimeline, Timeline.Window @@ -361,7 +362,8 @@ public final 
  • MediaLoadData

    -
    public MediaLoadData​(int dataType)
    +
    public MediaLoadData​(@DataType
    +                     int dataType)
    Creates an instance with the given dataType.
  • @@ -371,7 +373,8 @@ public final 
  • MediaLoadData

    -
    public MediaLoadData​(int dataType,
    +
    public MediaLoadData​(@DataType
    +                     int dataType,
                          int trackType,
                          @Nullable
                          Format trackFormat,
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/MediaSource.MediaSourceCaller.html b/docs/doc/reference/com/google/android/exoplayer2/source/MediaSource.MediaSourceCaller.html
    index a757cd8dc8..2067b4ff8b 100644
    --- a/docs/doc/reference/com/google/android/exoplayer2/source/MediaSource.MediaSourceCaller.html
    +++ b/docs/doc/reference/com/google/android/exoplayer2/source/MediaSource.MediaSourceCaller.html
    @@ -121,6 +121,10 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    The durations of each ad in the ad group, in microseconds.
  • + + + +
      +
    • +

      contentResumeOffsetUs

      +
      public final long contentResumeOffsetUs
      +
      The offset in microseconds which should be added to the content stream when resuming playback + after the ad group.
      +
    • +
    + + + +
      +
    • +

      isServerSideInserted

      +
      public final boolean isServerSideInserted
      +
      Whether this ad group is server-side inserted and part of the content stream.
      +
    • +
    @@ -420,14 +503,18 @@ public final int[] states

    Constructor Detail

    - +
    • AdGroup

      -
      public AdGroup()
      +
      public AdGroup​(long timeUs)
      Creates a new ad group with an unspecified number of ads.
      +
      +
      Parameters:
      +
      timeUs - The time of the ad group in the Timeline.Period, in microseconds, or C.TIME_END_OF_SOURCE to indicate a postroll ad.
      +
    @@ -462,6 +549,16 @@ public final int[] states lastPlayedAdIndex
    , or count if no later ads should be played. + + + +
      +
    • +

      shouldPlayAdGroup

      +
      public boolean shouldPlayAdGroup()
      +
      Returns whether the ad group has at least one ad that should be played.
      +
    • +
    @@ -469,7 +566,7 @@ public final int[] states
  • hasUnplayedAds

    public boolean hasUnplayedAds()
    -
    Returns whether the ad group has at least one ad that still needs to be played.
    +
    Returns whether the ad group has at least one ad that is neither played, skipped, nor failed.
  • @@ -499,6 +596,17 @@ public final int[] states
    + + + +
      +
    • +

      withTimeUs

      +
      @CheckResult
      +public AdPlaybackState.AdGroup withTimeUs​(long timeUs)
      +
      Returns a new instance with the timeUs set to the specified value.
      +
    • +
    @@ -551,6 +659,28 @@ public Returns a new instance with the specified ad durations, in microseconds. + + + + + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdPlaybackState.html b/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdPlaybackState.html index 8e0a7bbdea..56acc34b48 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdPlaybackState.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdPlaybackState.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}; +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}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -242,20 +242,6 @@ implements -AdPlaybackState.AdGroup[] -adGroups - -
    The ad groups.
    - - - -long[] -adGroupTimesUs - -
    The times of ad groups, in microseconds, relative to the start of the Timeline.Period they belong to.
    - - - long adResumePositionUs @@ -290,6 +276,13 @@ implements Ad playback state with no ads. + +int +removedAdGroupCount + +
    The number of ad groups the have been removed.
    + + @@ -338,6 +331,13 @@ implements   +AdPlaybackState.AdGroup +getAdGroup​(int adGroupIndex) + +
    Returns the specified AdPlaybackState.AdGroup.
    + + + int getAdGroupIndexAfterPositionUs​(long positionUs, long periodDurationUs) @@ -345,7 +345,7 @@ implements Returns the index of the next ad group after positionUs that should be played. - + int getAdGroupIndexForPositionUs​(long positionUs, long periodDurationUs) @@ -354,12 +354,12 @@ implements + int hashCode()   - + boolean isAdInErrorState​(int adGroupIndex, int adIndexInAdGroup) @@ -367,19 +367,19 @@ implements Returns whether the specified ad has been marked as in AD_STATE_ERROR. - + Bundle toBundle()
    Returns a Bundle representing the information stored in this object.
    - + String toString()   - + AdPlaybackState withAdCount​(int adGroupIndex, int adCount) @@ -387,14 +387,31 @@ implements Returns an instance with the number of ads in adGroupIndex resolved to adCount. - + +AdPlaybackState +withAdDurationsUs​(int adGroupIndex, + long... adDurationsUs) + +
    Returns an instance with the specified ad durations, in microseconds, in the specified ad + group.
    + + + AdPlaybackState withAdDurationsUs​(long[][] adDurationUs)
    Returns an instance with the specified ad durations, in microseconds.
    - + +AdPlaybackState +withAdGroupTimeUs​(int adGroupIndex, + long adGroupTimeUs) + +
    Returns an instance with the specified ad group time.
    + + + AdPlaybackState withAdLoadError​(int adGroupIndex, int adIndexInAdGroup) @@ -402,7 +419,7 @@ implements Returns an instance with the specified ad marked as having a load error. - + AdPlaybackState withAdResumePositionUs​(long adResumePositionUs) @@ -410,7 +427,7 @@ implements + AdPlaybackState withAdUri​(int adGroupIndex, int adIndexInAdGroup, @@ -419,14 +436,40 @@ implements Returns an instance with the specified ad URI. - + AdPlaybackState withContentDurationUs​(long contentDurationUs)
    Returns an instance with the specified content duration, in microseconds.
    - + +AdPlaybackState +withContentResumeOffsetUs​(int adGroupIndex, + long contentResumeOffsetUs) + +
    Returns an instance with the specified AdPlaybackState.AdGroup.contentResumeOffsetUs, in microseconds, + for the specified ad group.
    + + + +AdPlaybackState +withIsServerSideInserted​(int adGroupIndex, + boolean isServerSideInserted) + +
    Returns an instance with the specified value for AdPlaybackState.AdGroup.isServerSideInserted in the + specified ad group.
    + + + +AdPlaybackState +withNewAdGroup​(int adGroupIndex, + long adGroupTimeUs) + +
    Returns an instance with a new ad group.
    + + + AdPlaybackState withPlayedAd​(int adGroupIndex, int adIndexInAdGroup) @@ -434,7 +477,15 @@ implements Returns an instance with the specified ad marked as played. - + +AdPlaybackState +withRemovedAdGroupCount​(int removedAdGroupCount) + +
    Returns an instance with the specified number of removed ad + groups.
    + + + AdPlaybackState withSkippedAd​(int adGroupIndex, int adIndexInAdGroup) @@ -442,7 +493,7 @@ implements Returns an instance with the specified ad marked as skipped. - + AdPlaybackState withSkippedAdGroup​(int adGroupIndex) @@ -575,27 +626,6 @@ public final The number of ad groups. - - - -
      -
    • -

      adGroupTimesUs

      -
      public final long[] adGroupTimesUs
      -
      The times of ad groups, in microseconds, relative to the start of the Timeline.Period they belong to. A final element with the value - C.TIME_END_OF_SOURCE indicates a postroll ad.
      -
    • -
    - - - - @@ -616,6 +646,18 @@ public final The duration of the content period in microseconds, if known. C.TIME_UNSET otherwise. + + + +
      +
    • +

      removedAdGroupCount

      +
      public final int removedAdGroupCount
      +
      The number of ad groups the have been removed. Ad groups with indices between 0 + (inclusive) and removedAdGroupCount (exclusive) will be empty and must not be modified + by any of the with* methods.
      +
    • +
    @@ -666,6 +708,16 @@ public final  + + + @@ -722,6 +774,46 @@ public final Returns whether the specified ad has been marked as in AD_STATE_ERROR. + + + +
      +
    • +

      withAdGroupTimeUs

      +
      @CheckResult
      +public AdPlaybackState withAdGroupTimeUs​(int adGroupIndex,
      +                                         long adGroupTimeUs)
      +
      Returns an instance with the specified ad group time.
      +
      +
      Parameters:
      +
      adGroupIndex - The index of the ad group.
      +
      adGroupTimeUs - The new ad group time, in microseconds, or C.TIME_END_OF_SOURCE to + indicate a postroll ad.
      +
      Returns:
      +
      The updated ad playback state.
      +
      +
    • +
    + + + +
      +
    • +

      withNewAdGroup

      +
      @CheckResult
      +public AdPlaybackState withNewAdGroup​(int adGroupIndex,
      +                                      long adGroupTimeUs)
      +
      Returns an instance with a new ad group.
      +
      +
      Parameters:
      +
      adGroupIndex - The insertion index of the new group.
      +
      adGroupTimeUs - The ad group time, in microseconds, or C.TIME_END_OF_SOURCE to + indicate a postroll ad.
      +
      Returns:
      +
      The updated ad playback state.
      +
      +
    • +
    @@ -804,7 +896,22 @@ public @CheckResult public AdPlaybackState withAdDurationsUs​(long[][] adDurationUs) -
    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 removedAdGroupCount is 0.

    + + + + + +
      +
    • +

      withAdDurationsUs

      +
      @CheckResult
      +public AdPlaybackState withAdDurationsUs​(int adGroupIndex,
      +                                         long... adDurationsUs)
      +
      Returns an instance with the specified ad durations, in microseconds, in the specified ad + group.
    @@ -830,6 +937,47 @@ public Returns an instance with the specified content duration, in microseconds. + + + +
      +
    • +

      withRemovedAdGroupCount

      +
      @CheckResult
      +public AdPlaybackState withRemovedAdGroupCount​(int removedAdGroupCount)
      +
      Returns an instance with the specified number of removed ad + groups. + +

      Ad groups with indices between 0 (inclusive) and removedAdGroupCount + (exclusive) will be empty and must not be modified by any of the with* methods.

      +
    • +
    + + + + + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdsLoader.EventListener.html b/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdsLoader.EventListener.html index c283eb8b37..ba0c9c78be 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdsLoader.EventListener.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdsLoader.EventListener.html @@ -200,7 +200,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • onAdPlaybackState

    default void onAdPlaybackState​(AdPlaybackState adPlaybackState)
    -
    Called when the ad playback state has been updated. The number of ad groups may not change after the first call.
    +
    Called when the ad playback state has been updated. The number of ad groups may not change after the first call.
    Parameters:
    adPlaybackState - The new ad playback state.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdsMediaSource.html b/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdsMediaSource.html index 8e1dd0807d..a302cc4ac4 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdsMediaSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/ads/AdsMediaSource.html @@ -25,8 +25,8 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":10,"i3":42,"i4":10,"i5":10,"i6":10,"i7":10}; -var tabs = {65535:["t0","All 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}; +var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -224,7 +224,7 @@ extends -All Methods Instance Methods Concrete Methods Deprecated Methods  +All Methods Instance Methods Concrete Methods  Modifier and Type Method @@ -255,15 +255,6 @@ extends -Object -getTag() - -
    Deprecated. - -
    - - - protected void onChildSourceInfoRefreshed​(MediaSource.MediaPeriodId mediaPeriodId, MediaSource mediaSource, @@ -272,7 +263,7 @@ extends Called when the source info of a child source has been refreshed. - + protected void prepareSourceInternal​(TransferListener mediaTransferListener) @@ -280,14 +271,14 @@ extends + void releasePeriod​(MediaPeriod mediaPeriod)
    Releases the period.
    - + protected void releaseSourceInternal() @@ -377,20 +368,6 @@ extends - - - diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsMediaSource.html b/docs/doc/reference/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsMediaSource.html new file mode 100644 index 0000000000..12953346d4 --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsMediaSource.html @@ -0,0 +1,1041 @@ + + + + +ServerSideInsertedAdsMediaSource (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class ServerSideInsertedAdsMediaSource

    +
    +
    + +
    + +
    +
    + +
    +
    + +
    +
    +
    + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsUtil.html b/docs/doc/reference/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsUtil.html new file mode 100644 index 0000000000..a845dc81dd --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/source/ads/ServerSideInsertedAdsUtil.html @@ -0,0 +1,568 @@ + + + + +ServerSideInsertedAdsUtil (ExoPlayer library) + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class ServerSideInsertedAdsUtil

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.google.android.exoplayer2.source.ads.ServerSideInsertedAdsUtil
      • +
      +
    • +
    +
    +
      +
    • +
      +
      public final class ServerSideInsertedAdsUtil
      +extends Object
      +
      A static utility class with methods to work with server-side inserted ads.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          addAdGroupToAdPlaybackState

          +
          @CheckResult
          +public static AdPlaybackState addAdGroupToAdPlaybackState​(AdPlaybackState adPlaybackState,
          +                                                          long fromPositionUs,
          +                                                          long toPositionUs,
          +                                                          long contentResumeOffsetUs)
          +
          Adds a new server-side inserted ad group to an AdPlaybackState.
          +
          +
          Parameters:
          +
          adPlaybackState - The existing AdPlaybackState.
          +
          fromPositionUs - The position in the underlying server-side inserted ads stream at which + the ad group starts, in microseconds.
          +
          toPositionUs - The position in the underlying server-side inserted ads stream at which the + ad group ends, in microseconds.
          +
          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 toPositionUs-fromPositionUs keeps the original + stream timestamps after the ad group.
          +
          Returns:
          +
          The updated AdPlaybackState.
          +
          +
        • +
        + + + +
          +
        • +

          getStreamDurationUs

          +
          public static long getStreamDurationUs​(Player player,
          +                                       AdPlaybackState adPlaybackState)
          +
          Returns the duration of the underlying server-side inserted ads stream for the current Timeline.Period in the Player.
          +
          +
          Parameters:
          +
          player - The Player.
          +
          adPlaybackState - The AdPlaybackState defining the ad groups.
          +
          Returns:
          +
          The duration of the underlying server-side inserted ads stream, in microseconds, or + C.TIME_UNSET if it can't be determined.
          +
          +
        • +
        + + + +
          +
        • +

          getStreamPositionUs

          +
          public static long getStreamPositionUs​(Player player,
          +                                       AdPlaybackState adPlaybackState)
          +
          Returns the position in the underlying server-side inserted ads stream for the current playback + position in the Player.
          +
          +
          Parameters:
          +
          player - The Player.
          +
          adPlaybackState - The AdPlaybackState defining the ad groups.
          +
          Returns:
          +
          The position in the underlying server-side inserted ads stream, in microseconds, or + C.TIME_UNSET if it can't be determined.
          +
          +
        • +
        + + + +
          +
        • +

          getStreamPositionUs

          +
          public static long getStreamPositionUs​(long positionUs,
          +                                       MediaPeriodId mediaPeriodId,
          +                                       AdPlaybackState adPlaybackState)
          +
          Returns the position in the underlying server-side inserted ads stream for a position in a + MediaPeriod.
          +
          +
          Parameters:
          +
          positionUs - The position in the MediaPeriod, in microseconds.
          +
          mediaPeriodId - The MediaPeriodId of the MediaPeriod.
          +
          adPlaybackState - The AdPlaybackState defining the ad groups.
          +
          Returns:
          +
          The position in the underlying server-side inserted ads stream, in microseconds.
          +
          +
        • +
        + + + +
          +
        • +

          getMediaPeriodPositionUs

          +
          public static long getMediaPeriodPositionUs​(long positionUs,
          +                                            MediaPeriodId mediaPeriodId,
          +                                            AdPlaybackState adPlaybackState)
          +
          Returns the position in a MediaPeriod for a position in the underlying server-side + inserted ads stream.
          +
          +
          Parameters:
          +
          positionUs - The position in the underlying server-side inserted ads stream, in + microseconds.
          +
          mediaPeriodId - The MediaPeriodId of the MediaPeriod.
          +
          adPlaybackState - The AdPlaybackState defining the ad groups.
          +
          Returns:
          +
          The position in the MediaPeriod, in microseconds.
          +
          +
        • +
        + + + +
          +
        • +

          getStreamPositionUsForAd

          +
          public static long getStreamPositionUsForAd​(long positionUs,
          +                                            int adGroupIndex,
          +                                            int adIndexInAdGroup,
          +                                            AdPlaybackState adPlaybackState)
          +
          Returns the position in the underlying server-side inserted ads stream for a position in an ad + MediaPeriod.
          +
          +
          Parameters:
          +
          positionUs - The position in the ad MediaPeriod, in microseconds.
          +
          adGroupIndex - The ad group index of the ad.
          +
          adIndexInAdGroup - The index of the ad in the ad group.
          +
          adPlaybackState - The AdPlaybackState defining the ad groups.
          +
          Returns:
          +
          The position in the underlying server-side inserted ads stream, in microseconds.
          +
          +
        • +
        + + + +
          +
        • +

          getMediaPeriodPositionUsForAd

          +
          public static long getMediaPeriodPositionUsForAd​(long positionUs,
          +                                                 int adGroupIndex,
          +                                                 int adIndexInAdGroup,
          +                                                 AdPlaybackState adPlaybackState)
          +
          Returns the position in an ad MediaPeriod for a position in the underlying server-side + inserted ads stream.
          +
          +
          Parameters:
          +
          positionUs - The position in the underlying server-side inserted ads stream, in + microseconds.
          +
          adGroupIndex - The ad group index of the ad.
          +
          adIndexInAdGroup - The index of the ad in the ad group.
          +
          adPlaybackState - The AdPlaybackState defining the ad groups.
          +
          Returns:
          +
          The position in the ad MediaPeriod, in microseconds.
          +
          +
        • +
        + + + +
          +
        • +

          getStreamPositionUsForContent

          +
          public static long getStreamPositionUsForContent​(long positionUs,
          +                                                 int nextAdGroupIndex,
          +                                                 AdPlaybackState adPlaybackState)
          +
          Returns the position in the underlying server-side inserted ads stream for a position in a + content MediaPeriod.
          +
          +
          Parameters:
          +
          positionUs - The position in the content MediaPeriod, in microseconds.
          +
          nextAdGroupIndex - The next ad group index after the content, or C.INDEX_UNSET if + there is no following ad group. Ad groups from this index are not used to adjust the + position.
          +
          adPlaybackState - The AdPlaybackState defining the ad groups.
          +
          Returns:
          +
          The position in the underlying server-side inserted ads stream, in microseconds.
          +
          +
        • +
        + + + +
          +
        • +

          getMediaPeriodPositionUsForContent

          +
          public static long getMediaPeriodPositionUsForContent​(long positionUs,
          +                                                      int nextAdGroupIndex,
          +                                                      AdPlaybackState adPlaybackState)
          +
          Returns the position in a content MediaPeriod for a position in the underlying + server-side inserted ads stream.
          +
          +
          Parameters:
          +
          positionUs - The position in the underlying server-side inserted ads stream, in + microseconds.
          +
          nextAdGroupIndex - The next ad group index after the content, or C.INDEX_UNSET if + there is no following ad group. Ad groups from this index are not used to adjust the + position.
          +
          adPlaybackState - The AdPlaybackState defining the ad groups.
          +
          Returns:
          +
          The position in the content MediaPeriod, in microseconds.
          +
          +
        • +
        + + + +
          +
        • +

          getAdCountInGroup

          +
          public static int getAdCountInGroup​(AdPlaybackState adPlaybackState,
          +                                    int adGroupIndex)
          +
          Returns the number of ads in an ad group, treating an unknown number as zero ads.
          +
          +
          Parameters:
          +
          adPlaybackState - The AdPlaybackState.
          +
          adGroupIndex - The index of the ad group.
          +
          Returns:
          +
          The number of ads in the ad group.
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +
    + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.html b/docs/doc/reference/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.html index b5754a70b4..7bc877dc8c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.html @@ -164,7 +164,7 @@ extends Timeline -Timeline.Period, Timeline.Window
  • +Timeline.Period, Timeline.RemotableTimeline, Timeline.Window +
  • 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.ads.ServerSideInsertedAdsUtil
  • java.lang.Throwable (implements java.io.Serializable)
    • java.lang.Exception diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/Chunk.html b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/Chunk.html index dd3d034b3a..be9b9b9637 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/Chunk.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/Chunk.html @@ -193,8 +193,8 @@ implements long startTimeUs -
      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.
      @@ -222,7 +222,7 @@ implements int type -
      The type of the chunk.
      +
      The data type of the chunk.
      @@ -356,9 +356,9 @@ implements
    • type

      -
      public final int type
      -
      +
      @DataType
      +public final int type
      +
      The data type of the chunk. For reporting only.
    @@ -402,8 +402,8 @@ public final 

    startTimeUs

    public final long startTimeUs
    -
    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.
  • @@ -444,6 +444,7 @@ public final DataSource dataSource, DataSpec dataSpec, + @DataType int type, Format trackFormat, int trackSelectionReason, diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.html b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.html index e914db66ba..70678ae3e4 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.html @@ -849,11 +849,11 @@ implements continueLoading
     in interface SequenceableLoader
    Parameters:
    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.
    + 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.
    Returns:
    -
    True if progress was made, meaning that SequenceableLoader.getNextLoadPositionUs() will return - a different value than prior to the call. False otherwise.
    +
    True if progress was made, meaning that SequenceableLoader.getNextLoadPositionUs() will return a + different value than prior to the call. False otherwise.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/ChunkSource.html b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/ChunkSource.html index df663ff31c..d01923a659 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/ChunkSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/ChunkSource.html @@ -195,10 +195,10 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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.
    @@ -360,7 +360,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    - +
      @@ -368,17 +368,17 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

      onChunkLoadError

      boolean 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.
      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, getNextChunk(long, long, List, ChunkHolder) will be called to obtain the replacement diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/DataChunk.html b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/DataChunk.html index 8e5babdfc8..38aacb6ca6 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/DataChunk.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/DataChunk.html @@ -274,6 +274,7 @@ extends DataSource dataSource, DataSpec dataSpec, + @DataType int type, Format trackFormat, int trackSelectionReason, diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/MediaParserChunkExtractor.html b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/MediaParserChunkExtractor.html index 0fec6c2aba..f16a756590 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/chunk/MediaParserChunkExtractor.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/chunk/MediaParserChunkExtractor.html @@ -249,7 +249,7 @@ implements boolean -read​(ExtractorInput extractorInput) +read​(ExtractorInput input)
      Reads from the given ExtractorInput.
      @@ -379,7 +379,7 @@ implements
    • read

      -
      public boolean read​(ExtractorInput extractorInput)
      +
      public boolean read​(ExtractorInput input)
                    throws IOException
      Description copied from interface: ChunkExtractor
      Reads from the given ExtractorInput.
      @@ -387,7 +387,7 @@ implements Specified by:
      read in interface ChunkExtractor
      Parameters:
      -
      extractorInput - The input to read from.
      +
      input - The input to read from.
      Returns:
      Whether there is any data left to extract. Returns false if the end of input has been reached.
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/BaseUrlExclusionList.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/BaseUrlExclusionList.html new file mode 100644 index 0000000000..91eaaad68d --- /dev/null +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/BaseUrlExclusionList.html @@ -0,0 +1,407 @@ + + + + +BaseUrlExclusionList (ExoPlayer library) + + + + + + + + + + + + + +
      + +
      + +
      +
      + +

      Class BaseUrlExclusionList

      +
      +
      +
        +
      • java.lang.Object
      • +
      • +
          +
        • com.google.android.exoplayer2.source.dash.BaseUrlExclusionList
        • +
        +
      • +
      +
      +
        +
      • +
        +
        public final class BaseUrlExclusionList
        +extends Object
        +
        Holds the state of excluded base URLs to be used to select a base URL based on these exclusions.
        +
      • +
      +
      +
      + +
      +
      +
        +
      • + +
        +
          +
        • + + +

          Constructor Detail

          + + + +
            +
          • +

            BaseUrlExclusionList

            +
            public BaseUrlExclusionList()
            +
            Creates an instance.
            +
          • +
          +
        • +
        +
        + +
        +
          +
        • + + +

          Method Detail

          + + + +
            +
          • +

            exclude

            +
            public void exclude​(BaseUrl baseUrlToExclude,
            +                    long exclusionDurationMs)
            +
            Excludes the given base URL.
            +
            +
            Parameters:
            +
            baseUrlToExclude - The base URL to exclude.
            +
            exclusionDurationMs - The duration of exclusion, in milliseconds.
            +
            +
          • +
          + + + +
            +
          • +

            selectBaseUrl

            +
            @Nullable
            +public BaseUrl selectBaseUrl​(List<BaseUrl> baseUrls)
            +
            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 + exclude(BaseUrl, long). The base URL to use is then selected from the remaining base + URLs by priority and weight.

            +
            +
            Parameters:
            +
            baseUrls - The list of base URLs to select from.
            +
            Returns:
            +
            The selected base URL after exclusion or null if all elements have been excluded.
            +
            +
          • +
          + + + +
            +
          • +

            getPriorityCountAfterExclusion

            +
            public int getPriorityCountAfterExclusion​(List<BaseUrl> baseUrls)
            +
            Returns the number of priority levels for the given list of base URLs after exclusion.
            +
            +
            Parameters:
            +
            baseUrls - The list of base URLs.
            +
            Returns:
            +
            The number of priority levels after exclusion.
            +
            +
          • +
          + + + +
            +
          • +

            getPriorityCount

            +
            public static int getPriorityCount​(List<BaseUrl> baseUrls)
            +
            Returns the number of priority levels of the given list of base URLs.
            +
            +
            Parameters:
            +
            baseUrls - The list of base URLs.
            +
            Returns:
            +
            The number of priority levels before exclusion.
            +
            +
          • +
          + + + +
            +
          • +

            reset

            +
            public void reset()
            +
            Resets the state.
            +
          • +
          +
        • +
        +
        +
      • +
      +
      +
      +
      + + + + diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashChunkSource.Factory.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashChunkSource.Factory.html index 6fa5fc1206..4fb04686e4 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashChunkSource.Factory.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashChunkSource.Factory.html @@ -153,8 +153,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); DashChunkSource -createDashChunkSource​(LoaderErrorThrower manifestLoaderErrorThrower, +createDashChunkSource​(LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, int[] adaptationSetIndices, ExoTrackSelection trackSelection, @@ -183,7 +184,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

      Method Detail

      - +
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashMediaSource.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashMediaSource.html index 68d4cb1851..6e41c2dd5d 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashMediaSource.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashMediaSource.html @@ -25,8 +25,8 @@ catch(err) { } //--> -var data = {"i0":10,"i1":10,"i2":42,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10}; -var tabs = {65535:["t0","All 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}; +var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -229,7 +229,7 @@ extends -All Methods Instance Methods Concrete Methods Deprecated Methods  +All Methods Instance Methods Concrete Methods  Modifier and Type Method @@ -237,7 +237,7 @@ extends MediaPeriod -createPeriod​(MediaSource.MediaPeriodId periodId, +createPeriod​(MediaSource.MediaPeriodId id, Allocator allocator, long startPositionUs) @@ -252,22 +252,13 @@ extends -Object -getTag() - -
    Deprecated. - -
    - - - void maybeThrowSourceInfoRefreshError()
    Throws any pending error encountered while loading or refreshing source information.
    - + protected void prepareSourceInternal​(TransferListener mediaTransferListener) @@ -275,21 +266,21 @@ extends + void releasePeriod​(MediaPeriod mediaPeriod)
    Releases the period.
    - + protected void releaseSourceInternal() - + void replaceManifestUri​(Uri manifestUri) @@ -404,20 +395,6 @@ public static final long DEFAULT_LIVE_PRESENTATION_DELAY_MS
    - - - - @@ -477,7 +454,7 @@ public 
  • createPeriod

    -
    public MediaPeriod createPeriod​(MediaSource.MediaPeriodId periodId,
    +
    public MediaPeriod createPeriod​(MediaSource.MediaPeriodId id,
                                     Allocator allocator,
                                     long startPositionUs)
    Description copied from interface: MediaSource
    @@ -488,7 +465,7 @@ public Parameters: -
    periodId - The identifier of the period.
    +
    id - The identifier of the period.
    allocator - An Allocator from which to obtain media buffer allocations.
    startPositionUs - The expected start position, in microseconds.
    Returns:
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashUtil.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashUtil.html index 7d7ca9d48b..6ffa975c31 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashUtil.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DashUtil.html @@ -25,7 +25,7 @@ catch(err) { } //--> -var data = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9}; +var data = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9,"i5":9,"i6":9,"i7":9,"i8":9}; var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -162,6 +162,16 @@ extends +static DataSpec +buildDataSpec​(String baseUrl, + RangedUri requestUri, + String cacheKey, + int flags) + +
    Builds a DataSpec for a given RangedUri belonging to Representation.
    + + + static ChunkIndex loadChunkIndex​(DataSource dataSource, int trackType, @@ -170,7 +180,17 @@ extends Loads initialization and index data for the representation and returns the ChunkIndex. - + +static ChunkIndex +loadChunkIndex​(DataSource dataSource, + int trackType, + Representation representation, + int baseUrlIndex) + +
    Loads initialization and index data for the representation and returns the ChunkIndex.
    + + + static Format loadFormatWithDrmInitData​(DataSource dataSource, Period period) @@ -178,7 +198,18 @@ extends Loads a Format for acquiring keys for a given period in a DASH manifest. - + +static void +loadInitializationData​(ChunkExtractor chunkExtractor, + DataSource dataSource, + Representation representation, + boolean loadIndex) + +
    Loads initialization data for the representation and optionally index data then returns + a BundledChunkExtractor which contains the output.
    + + + static DashManifest loadManifest​(DataSource dataSource, Uri uri) @@ -186,7 +217,7 @@ extends Loads a DASH manifest. - + static Format loadSampleFormat​(DataSource dataSource, int trackType, @@ -195,6 +226,16 @@ extends Loads initialization data for the representation and returns the sample Format. + +static Format +loadSampleFormat​(DataSource dataSource, + int trackType, + Representation representation, + int baseUrlIndex) + +
    Loads initialization data for the representation and returns the sample Format.
    + +
    -
    Builds a DataSpec for a given RangedUri belonging to Representation.
    +
    Builds a DataSpec for a given RangedUri belonging to Representation. + +

    Uses the first base URL of the representation to build the data spec.

    Parameters:
    representation - The Representation to which the request belongs.
    @@ -282,6 +348,32 @@ public static  + + +
      +
    • +

      loadSampleFormat

      +
      @Nullable
      +public static Format loadSampleFormat​(DataSource dataSource,
      +                                      int trackType,
      +                                      Representation representation,
      +                                      int baseUrlIndex)
      +                               throws IOException
      +
      Loads initialization data for the representation and returns the sample Format.
      +
      +
      Parameters:
      +
      dataSource - The source from which the data should be loaded.
      +
      trackType - The type of the representation. Typically one of the C TRACK_TYPE_* constants.
      +
      representation - The representation which initialization chunk belongs to.
      +
      baseUrlIndex - The index of the base URL to be picked from the list of base URLs.
      +
      Returns:
      +
      the sample Format of the given representation.
      +
      Throws:
      +
      IOException - Thrown when there is an error while loading.
      +
      +
    • +
    @@ -293,7 +385,9 @@ public static Representation representation) throws IOException -
    Loads initialization data for the representation and returns the sample Format.
    +
    Loads initialization data for the representation and returns the sample Format. + +

    Uses the first base URL for loading the format.

    Parameters:
    dataSource - The source from which the data should be loaded.
    @@ -306,10 +400,37 @@ public static  + + +
      +
    • +

      loadChunkIndex

      +
      @Nullable
      +public static ChunkIndex loadChunkIndex​(DataSource dataSource,
      +                                        int trackType,
      +                                        Representation representation,
      +                                        int baseUrlIndex)
      +                                 throws IOException
      +
      Loads initialization and index data for the representation and returns the ChunkIndex.
      +
      +
      Parameters:
      +
      dataSource - The source from which the data should be loaded.
      +
      trackType - The type of the representation. Typically one of the C TRACK_TYPE_* constants.
      +
      representation - The representation which initialization chunk belongs to.
      +
      baseUrlIndex - The index of the base URL with which to resolve the request URI.
      +
      Returns:
      +
      The ChunkIndex of the given representation, or null if no initialization or + index data exists.
      +
      Throws:
      +
      IOException - Thrown when there is an error while loading.
      +
      +
    • +
    -
  • @@ -291,7 +292,7 @@ implements +
      @@ -299,6 +300,7 @@ implements public DashChunkSource createDashChunkSource​(LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, int[] adaptationSetIndices, ExoTrackSelection trackSelection, @@ -312,10 +314,11 @@ implements TransferListener transferListener)
      Specified by:
      -
      createDashChunkSource in interface DashChunkSource.Factory
      +
      createDashChunkSource in interface DashChunkSource.Factory
      Parameters:
      manifestLoaderErrorThrower - Throws errors affecting loading of manifests.
      manifest - The initial manifest.
      +
      baseUrlExclusionList - The base URL exclusion list.
      periodIndex - The index of the corresponding period in the manifest.
      adaptationSetIndices - The indices of the corresponding adaptation sets in the period.
      trackSelection - The track selection.
      diff --git a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.RepresentationHolder.html b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.RepresentationHolder.html index 9a5e3a51e9..185f226c15 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.RepresentationHolder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.RepresentationHolder.html @@ -166,6 +166,11 @@ extends segmentIndex   + +BaseUrl +selectedBaseUrl +  +
    @@ -263,6 +268,15 @@ extends public final Representation representation + + + +
      +
    • +

      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 d06c6cca44..f9f6b1e2bb 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 @@ implements 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 @@ implements 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 @@ implements +
      @@ -411,6 +412,7 @@ implements ChunkExtractor.Factory chunkExtractorFactory, LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, int[] adaptationSetIndices, ExoTrackSelection trackSelection, @@ -428,6 +430,7 @@ implements +
        @@ -640,20 +643,20 @@ implements 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 @@ implements 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 f8ba12a0bb..c7ebfc03cf 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 @@ implements TrackOutput.CryptoData encryptionData) + TrackOutput.CryptoData cryptoData)
        Called when metadata associated with a sample has been extracted from the stream.
        @@ -372,7 +372,7 @@ implements 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 @@ implements 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 c7fe078e01..45d6f90fde 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 @@ extends

      type

      public final int type
      -
      +
      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 0000000000..4845528f95 --- /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 03b57388fe..cca2123239 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 @@ implements 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 @@ implements 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 @@ implements

    timeShiftBufferDepthMs

    public final long timeShiftBufferDepthMs
    -
    +
    The timeShiftBufferDepth value in milliseconds, or C.TIME_UNSET if not present.
    @@ -430,8 +428,8 @@ implements

    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 f23c341acd..e9029a73e0 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 @@ extends Description -String -baseUrl +ImmutableList<BaseUrl> +baseUrls   @@ -203,8 +203,8 @@ extends Description -RepresentationInfo​(Format format, - String baseUrl, +RepresentationInfo​(Format format, + List<BaseUrl> baseUrls, SegmentBase segmentBase, String drmSchemeType, ArrayList<DrmInitData.SchemeData> drmSchemeDatas, @@ -255,13 +255,13 @@ extends public final Format format - + @@ -320,14 +320,14 @@ public final  + @@ -217,9 +217,9 @@ extends Description -SingleSegmentRepresentation​(long revisionId, +SingleSegmentRepresentation​(long revisionId, Format format, - String baseUrl, + List<BaseUrl> baseUrls, SegmentBase.SingleSegmentBase segmentBase, List<Descriptor> inbandEventStreams, String cacheKey, @@ -286,7 +286,7 @@ extends Representation -getInitializationUri, newInstance, newInstance, newInstance +getInitializationUri, newInstance, newInstance, newInstance diff --git a/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleDecoder.html b/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleDecoder.html index 1d61b0c4f6..9adf827c7c 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleDecoder.html +++ b/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleDecoder.html @@ -191,8 +191,8 @@ extends void setPositionUs​(long positionUs)
    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.

    Parameters:
    positionUs - The current playback position in microseconds.
    diff --git a/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleInputBuffer.html b/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleInputBuffer.html index 6d42874e28..c1fc18ff01 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleInputBuffer.html +++ b/docs/doc/reference/com/google/android/exoplayer2/text/SubtitleInputBuffer.html @@ -177,8 +177,7 @@ extends
    long subsampleOffsetUs -
    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.
    @@ -264,8 +263,7 @@ extends

    subsampleOffsetUs

    public long subsampleOffsetUs
    -
    +
    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.
    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 09ebc334f6..41665a12c8 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 @@ implements 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 fd7f9850d2..e5e49705ff 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 @@ implements 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 @@ public int supportsFormat​(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 @@ public int supportsFormat​(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
      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 b8757e209c..3c27a1913c 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 @@ public public void setPositionUs​(long positionUs)
      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 f378cf37f5..9fd5c0dbbe 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 @@ extends public void setPositionUs​(long positionUs)
      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 205ec85f82..414596a985 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 @@ extends 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 e56d16c43d..a0b7249618 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); -
  • 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 2b734d10d4..2e4ca98d51 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 @@ extends WebvttCssStyle -setFontSizeUnit​(short unit) +setFontSizeUnit​(int unit)   @@ -621,7 +621,16 @@ extends 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 @@ extends 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 @@ public 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 bfa08069b7..d02f0486da 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    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,16 +239,32 @@ extends static DefaultTrackSelector.Parameters +DEFAULT + +
    Deprecated. +
    This instance is not configured using Context constraints.
    +
    + + + +static DefaultTrackSelector.Parameters DEFAULT_WITHOUT_CONTEXT
    An instance with default values, except those obtained from the Context.
    + +int +disabledTextTrackSelectionFlags + +
    Bitmask of selection flags that are disabled for text track selections.
    + + 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.
    @@ -262,109 +279,7 @@ extends boolean exceedVideoConstraintsIfNecessary -
    Whether to exceed the maxVideoWidth, maxVideoHeight and maxVideoBitrate constraints when no selection can be made otherwise.
    - - - -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 -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 - -
    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 @@ extends 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.
    - - @@ -653,74 +490,6 @@ extends - - -
      -
    • -

      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 @@ extends

    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 @@ extends - - -
      -
    • -

      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 @@ extends - 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 2361d274a0..cb94cbd21e 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 @@ extends 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 @@ public final 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 @@ public final 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 6220e9a8f9..be9e02a8d6 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 @@ extends Constructors  -Constructor +Modifier +Constructor 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 @@ extends 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 @@ extends 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 @@ extends + +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 @@ public 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 @@ public Builder()
    + + + +
      +
    • +

      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 @@ public Builder()
    - +
    • -

      setDisabledTextTrackSelectionFlags

      -
      public TrackSelectionParameters.Builder setDisabledTextTrackSelectionFlags​(@SelectionFlags
      -                                                                           int disabledTextTrackSelectionFlags)
      -
      Sets a bitmask of selection flags that are disabled for text track selections.
      +

      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:
      -
      disabledTextTrackSelectionFlags - A bitmask of C.SelectionFlags that are - disabled for text track selections.
      +
      forceLowestBitrate - Whether to force selection of the single lowest bitrate audio and + video tracks.
      +
      Returns:
      +
      This builder.
      +
      +
    • +
    + + + +
      +
    • +

      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:
      +
      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 b2918fb67c..fcfdea1465 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 @@ loadScripts(document, 'script');
    • Summary: 
    • Nested | 
    • Field | 
    • -
    • Constr | 
    • +
    • Constr | 
    • Method
    @@ -215,13 +215,92 @@ implements -int -disabledTextTrackSelectionFlags +boolean +forceHighestSupportedBitrate -
    Bitmask of selection flags that are disabled for text track selections.
    +
    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 +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> preferredAudioLanguages @@ -229,6 +308,14 @@ implements +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 @@ implements +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 @@ implements + +
      @@ -373,6 +514,151 @@ public static final  + + + + + + +
        +
      • +

        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 @@ public final int 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 @@ public final int preferredTextRoleFlags 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 26fa5d0f64..aa3d848324 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 @@ extends 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 @@ extends - + static boolean hasTrackOfType​(TrackSelectionArray trackSelections, int trackType) @@ -194,7 +202,7 @@ extends 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 @@ extends -
    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 2cd9c3ad25..78f23a7318 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 @@ extends 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 @@ extends 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 @@ extends 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 7064bd5762..3f67e9ba0f 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 0a9be52427..7464e1a1b0 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 adc3cb9589..88ecb8da1f 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 @@ extends @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 0000000000..a3d13215ab --- /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 fae4868026..1c7fbafebe 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 @@ implements public void setKeyTimeIncrement​(long time)
    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 @@ implements 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 25670a93bb..587cdfab2b 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 @@ extends 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 @@ extends 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 @@ extends
    void setControlDispatcher​(ControlDispatcher controlDispatcher) - +
    Deprecated. +
    Use a ForwardingPlayer and pass it to setPlayer(Player) instead.
    +
    @@ -616,123 +607,96 @@ extends 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,34 +988,19 @@ public  - - - @@ -1110,32 +1059,6 @@ public void setPlaybackPreparer​(@Nullable
  • - - - - - - - - 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 c1a757a175..6d068b82a2 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 @@ extends 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 @@ extends 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 @@ extends + + + + @@ -572,6 +603,22 @@ extends + + + + 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 9beec0d3b9..dc1daf0208 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    • +
      All Known Implementing Classes:
      +
      DefaultMediaDescriptionAdapter
      +
      +
      Enclosing class:
      PlayerNotificationManager
      @@ -213,6 +217,8 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
      Parameters:
      player - The Player for which a notification is being built.
      +
      Returns:
      +
      The content title for the current media item.
    @@ -230,6 +236,8 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ default 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 @@ default 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 5713b87567..d23ecfc193 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 @@ loadScripts(document, 'script');
  • Summary: 
  • Nested | 
  • Field | 
  • -
  • Constr | 
  • +
  • Constr | 
  • Method
  • @@ -140,7 +140,7 @@ extends 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 @@ extends
    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. -
  • fastForwardIncrementMs - Sets the fast forward increment. If set to zero the - fast forward action is not 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. +
  • 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 @@ extends
    -

    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 @@ extends
    - -
    - -
    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 efaea35dab..3a27f6c5fb 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 @@ loadScripts(document, 'script'); @@ -124,6 +124,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • java.io.IOException
  • +
  • +
    • @@ -147,7 +152,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    public static final class AssetDataSource.AssetDataSourceException
    -extends IOException
    +extends DataSourceException
    Thrown when an IOException is encountered reading a local asset.
    See Also:
    @@ -159,6 +164,23 @@ extends
    + +
    • @@ -147,7 +152,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    public static class ContentDataSource.ContentDataSourceException
    -extends IOException
    +extends DataSourceException
    Thrown when an IOException is encountered reading from a content URI.
    See Also:
    @@ -159,6 +164,23 @@ extends @@ -236,7 +264,8 @@ extends isCausedByPositionOutOfRange​(IOException e)
    Returns whether the given IOException was caused by a DataSourceException whose - reason is POSITION_OUT_OF_RANGE in its cause stack.
    + reason is PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE in its + cause stack. @@ -276,7 +305,11 @@ extends
  • POSITION_OUT_OF_RANGE

    -
    public static final int POSITION_OUT_OF_RANGE
    +
    @Deprecated
    +public static final int POSITION_OUT_OF_RANGE
    +
    Indicates that the starting position of the request was outside the bounds of the data.
    @@ -291,8 +324,10 @@ extends
  • reason

    -
    public final int reason
    -
    +
    @ErrorCode
    +public final int reason
    +
    The reason of this DataSourceException, should be one of the ERROR_CODE_IO_* in + PlaybackException.ErrorCode.
  • @@ -308,14 +343,72 @@ extends - 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 e0742c6eee..b612dd7e2f 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 @@ extends 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 5f71239faa..11cdbf631c 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 @@ implements 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 @@ implements 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 @@ implements 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 @@ implements public 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.
    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 ac43060636..2a57c81f66 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 @@ implements onBytesTransferred​(DataSource source, DataSpec dataSpec, boolean isNetwork, - int bytes) + int bytesTransferred)
    Called incrementally during a transfer.
    @@ -698,7 +698,7 @@ public DefaultBandwidthMeter()
    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 @@ public DefaultBandwidthMeter()
    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 1e4cec5fca..f3e9c9ea1d 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 @@ implements int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -472,7 +472,7 @@ implements 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 @@ implements 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 4101cc270e..b72dd71210 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 @@ implements 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 @@ public final  + + +
      +
    • +

      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 2b2a5e3f67..30798524c2 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 @@ implements int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -684,7 +684,7 @@ public 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 @@ public 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 1149d29b83..34cff85ae8 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 @@ implements LoadErrorHandlingPolicy -LoadErrorHandlingPolicy.LoadErrorInfo +LoadErrorHandlingPolicy.FallbackOptions, LoadErrorHandlingPolicy.FallbackSelection, LoadErrorHandlingPolicy.FallbackType, LoadErrorHandlingPolicy.LoadErrorInfo @@ -175,13 +175,20 @@ implements 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 @@ implements + 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 @@ implements 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 @@ implements Retries for any exception that is not a subclass of ParserException, FileNotFoundException, HttpDataSource.CleartextNotPermittedException or Loader.UnexpectedLoaderException.
    + +protected boolean +isEligibleForFallback​(IOException exception) + +
    Returns whether an error should trigger a fallback if possible.
    + + @@ -326,17 +357,48 @@ implements + + +
      +
    • +

      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.
      +

      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
      +
      Constant Field Values
    @@ -386,23 +448,34 @@ implements + @@ -421,14 +494,15 @@ implements 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 @@ implements 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 2f3277a598..3161c8ea2a 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 @@ implements int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -369,7 +369,7 @@ implements public int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input. @@ -383,7 +383,7 @@ implements 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 aee4749d9f..59154b326d 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 @@ loadScripts(document, 'script'); @@ -124,6 +124,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • java.io.IOException
  • + +
    • @@ -147,7 +152,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    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 @@ extends @@ -230,6 +242,20 @@ extends +
  • + + +

    Methods inherited from class com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException

    +createForIOException
  • + + +
    • diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.HttpDataSourceException.Type.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.HttpDataSourceException.Type.html index a23402cca8..5862ff93a4 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.HttpDataSourceException.Type.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.HttpDataSourceException.Type.html @@ -116,6 +116,8 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
      @Documented
       @Retention(SOURCE)
       public static @interface HttpDataSource.HttpDataSourceException.Type
      +
    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 591fe8cf20..4385a27604 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 @@ loadScripts(document, 'script');
  • Detail: 
  • Field | 
  • Constr | 
  • -
  • Method
  • +
  • Method
  • @@ -124,6 +130,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • java.io.IOException
  • + +
    • @@ -151,7 +162,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    public static class HttpDataSource.HttpDataSourceException
    -extends IOException
    +extends DataSourceException
    Thrown when an error is encountered when trying to read from a HttpDataSource.
    See Also:
    @@ -180,7 +191,9 @@ extends static interface  HttpDataSource.HttpDataSourceException.Type -  + +
    The type of operation that produced the error.
    + @@ -215,19 +228,32 @@ extends static int TYPE_CLOSE -  + +
    The error occurred in closing a HttpDataSource.
    + static int TYPE_OPEN -  + +
    The error occurred reading data from a HttpDataSource.
    + static int TYPE_READ -  + +
    The error occurred in opening a HttpDataSource.
    + + @@ -247,26 +273,81 @@ extends 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 @@ extends +All Methods Static Methods Concrete Methods  + +Modifier and Type +Method +Description + + +static HttpDataSource.HttpDataSourceException +createForIOException​(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 @@ public final int type + + + + @@ -395,10 +528,37 @@ public final int type + + + + @@ -407,23 +567,104 @@ public final int type + + + + + + + + + + + + +
    + 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 6e7474b861..a7a1f22c73 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • java.io.IOException
  • +
  • @@ -241,6 +253,20 @@ extends +
  • + + +

    Methods inherited from class com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException

    +createForIOException
  • + + + @@ -248,31 +260,34 @@ extends 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 @@ extends +
  • + + +

    Methods inherited from class com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException

    +createForIOException
  • + + + @@ -396,11 +426,12 @@ public InvalidResponseCodeException​(int responseCode, Map<String,​List<String>> headerFields, DataSpec dataSpec) - +
      @@ -409,6 +440,8 @@ public InvalidResponseCodeException​(int responseCode,
      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 bfc3d24a6b..b43a3548a7 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
      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 5da301039f..2c98063ba6 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 @@ extends 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 @@ extends int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -405,7 +405,7 @@ extends 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 @@ extends 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 0000000000..319d46499b --- /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 0000000000..9c0bf0ceab --- /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 0000000000..74accacca2 --- /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 253bb32aea..2a16b6f494 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 @@ loadScripts(document, 'script'); @@ -126,16 +126,18 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + +
    +
      +
    • + + +

      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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

      Method Summary

      - + - - + + - - - - - + + + + + - - - - - - - - - - @@ -607,8 +607,8 @@ implements 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 1668d01983..e9b816c731 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 @@ implements maybeThrowError​(int minRetryCount)
      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.
      +
      longgetRetryDelayMsFor​(LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo) +
      Returns whether a loader can retry on encountering an error, and if so the duration to wait + before retrying.
      default longgetRetryDelayMsFor​(int dataType, - long loadDurationMs, - IOException exception, - int errorCount) -
      Deprecated. - -
      -
      default longgetRetryDelayMsFor​(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.
      -
      default void onLoadTaskConcluded​(long loadTaskId) @@ -247,6 +282,46 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
      • + +
        +
          +
        • + + +

          Field Detail

          + + + +
            +
          • +

            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
            +
            +
          • +
          + + + +
            +
          • +

            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).
            +
            +
            See Also:
            +
            Constant Field Values
            +
            +
          • +
          +
        • +
        +
          @@ -254,73 +329,48 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

          Method Detail

          - + - - - - - - - -
          • 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 @@ default long getRetryDelayMsFor​(int dataType,
        • 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 @@ default long getRetryDelayMsFor​(int dataType, 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 475e85eace..f3baf718cf 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 @@ implements 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.
      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 @@ implements public void 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. 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 72ce2a24c5..f8d97d80d9 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 53fed6430d..03587a0e21 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 @@ implements int read​(byte[] buffer, int offset, - int max) + int length)
    Reads up to length bytes of data from the input.
    @@ -370,7 +370,7 @@ implements 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 @@ implements 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 465cea787f..2c3b178c47 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 @@ loadScripts(document, 'script'); @@ -124,6 +124,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • java.io.IOException
  • + +
    • @@ -147,7 +152,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    public static class RawResourceDataSource.RawResourceDataSourceException
    -extends IOException
    +extends DataSourceException
    Thrown when an IOException is encountered reading from a raw resource.
    See Also:
    @@ -159,6 +164,23 @@ extends 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 b5b438fdfb..c581625984 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 @@ extends int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -440,7 +440,7 @@ extends 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 @@ extends 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 832e55d834..780b84da36 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 @@ implements int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -373,7 +373,7 @@ implements 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 @@ implements 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 9df21501ab..018b034925 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 @@ implements int read​(byte[] buffer, int offset, - int readLength) + int length)
    Reads up to length bytes of data from the input.
    @@ -428,7 +428,7 @@ implements 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 @@ implements 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 902e8cc256..576ff633f6 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 @@ implements int read​(byte[] buffer, int offset, - int max) + int length)
    Reads up to length bytes of data from the input.
    @@ -358,7 +358,7 @@ implements 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 @@ implements 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 315a0c04e1..229d37e391 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 1f5bf3f919..a4bb05412f 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 @@ loadScripts(document, 'script'); @@ -124,6 +124,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • java.io.IOException
  • + +
    • @@ -147,7 +152,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    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 @@ extends 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 2c07727ed8..b80af075a5 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 @@ implements void -write​(byte[] data, +write​(byte[] buffer, int offset, int length) @@ -335,7 +335,7 @@ implements
  • write

    -
    public void write​(byte[] data,
    +
    public void write​(byte[] buffer,
                       int offset,
                       int length)
                throws IOException
    @@ -345,7 +345,7 @@ implements 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 bbc22ba773..28403c9b43 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 @@ implements 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 @@ implements
  • read

    -
    public int read​(byte[] data,
    +
    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. @@ -366,9 +366,9 @@ implements Specified by:
    read in interface DataReader
    Parameters:
    -
    data - 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.
    -
    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/package-summary.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/package-summary.html index c52a2571dc..afe9b51fbf 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/package-summary.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/package-summary.html @@ -190,7 +190,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); LoadErrorHandlingPolicy -
    Defines how errors encountered by loaders are handled.
    +
    A policy that defines how load errors are handled.
    @@ -382,9 +382,9 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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.
    @@ -413,6 +413,18 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); +LoadErrorHandlingPolicy.FallbackOptions + +
    Holds information about the available fallback options.
    + + + +LoadErrorHandlingPolicy.FallbackSelection + +
    A selected fallback option.
    + + + LoadErrorHandlingPolicy.LoadErrorInfo
    Holds information about a load task error.
    @@ -575,7 +587,15 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); HttpDataSource.HttpDataSourceException.Type -  + +
    The type of operation that produced the error.
    + + + +LoadErrorHandlingPolicy.FallbackType + +
    Fallback type.
    + diff --git a/docs/doc/reference/com/google/android/exoplayer2/upstream/package-tree.html b/docs/doc/reference/com/google/android/exoplayer2/upstream/package-tree.html index e9178a52e3..cc83adbbf2 100644 --- a/docs/doc/reference/com/google/android/exoplayer2/upstream/package-tree.html +++ b/docs/doc/reference/com/google/android/exoplayer2/upstream/package-tree.html @@ -145,6 +145,8 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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.upstream.ParsingLoadable<T> (implements com.google.android.exoplayer2.upstream.Loader.Loadable)
  • com.google.android.exoplayer2.upstream.PriorityDataSource (implements com.google.android.exoplayer2.upstream.DataSource)
  • @@ -159,9 +161,10 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • @@ -222,6 +227,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 2d4cd22862..cc82444189 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 @@ extends 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 0000000000..74e3ce1859 --- /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 694c5eb857..22623a7b09 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 @@ implements void onPlayWhenReadyChanged​(boolean playWhenReady, - int playbackState) + int reason)
    Called when the value returned from Player.getPlayWhenReady() changes.
    @@ -269,14 +269,14 @@ implements 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 0b9bc33594..c2f2e354f1 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 @@ implements 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 @@ implements void onAudioDisabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters) + DecoderCounters decoderCounters)
    Called when an audio renderer is disabled.
    @@ -269,7 +269,7 @@ implements void onAudioEnabled​(AnalyticsListener.EventTime eventTime, - DecoderCounters counters) + DecoderCounters decoderCounters)
    Called when an audio renderer is enabled.
    @@ -351,7 +351,7 @@ implements void onDrmSessionManagerError​(AnalyticsListener.EventTime eventTime, - Exception e) + Exception error)
    Called when a drm error occurs.
    @@ -366,7 +366,7 @@ implements void onDroppedVideoFrames​(AnalyticsListener.EventTime eventTime, - int count, + int droppedFrames, long elapsedMs)
    Called after video frames have been dropped.
    @@ -469,8 +469,8 @@ implements void -onPlayerError​(AnalyticsListener.EventTime eventTime, - ExoPlaybackException e) +onPlayerError​(AnalyticsListener.EventTime eventTime, + PlaybackException error)
    Called when a fatal player error occurred.
    @@ -530,14 +530,6 @@ implements 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 @@ implements Called when the output surface size changed. - + void onTimelineChanged​(AnalyticsListener.EventTime eventTime, int reason) @@ -553,16 +545,16 @@ implements 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 @@ implements + void onVideoDecoderInitialized​(AnalyticsListener.EventTime eventTime, String decoderName, long initializationDurationMs)   - + void onVideoDecoderReleased​(AnalyticsListener.EventTime eventTime, String decoderName) @@ -586,23 +578,23 @@ implements 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 @@ implements 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 @@ implements + void onVolumeChanged​(AnalyticsListener.EventTime eventTime, float volume) @@ -641,7 +633,7 @@ implements 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 @@ implements + @@ -953,7 +947,7 @@ implements

    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 @@ implements 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 @@ implements

    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 @@ implements 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 @@ implements

    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 @@ implements 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 @@ implements

    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 @@ implements 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 @@ implements

    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 @@ implements 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 @@ implements

    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 @@ implements 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 @@ implements 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 @@ implements

    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 @@ implements 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 17bc263de2..a3e0355488 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 2bdf551ec3..32f92591b7 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 @@ extends 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 9123bfcbc9..175bce0496 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 @@ extends 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 @@ extends 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 @@ extends 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 e93d2f0f62..0955ea3899 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends

    Field Detail

    - + + + +
      +
    • +

      MODE_NO_OFFSET

      +
      public static final long MODE_NO_OFFSET
      +
      A special firstSampleTimestampUs value indicating that presentation timestamps should + not be offset. In this mode: + +
      +
      +
      See Also:
      +
      Constant Field Values
      +
      +
    • +
    + @@ -331,7 +365,7 @@ extends
    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 @@ extends

    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 @@ extends

    getFirstSampleTimestampUs

    public long getFirstSampleTimestampUs()
    -
    +
    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 @@ extends

    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 @@ extends

    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 @@ extends

    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 78a4e60fe9..e128a0a513 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 @@ extends 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 @@ extends Performs relative resolution of a referenceUri with respect to a baseUri. - + static Uri resolveToUri​(String baseUri, String referenceUri) @@ -238,6 +245,17 @@ extends + + + +
      +
    • +

      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 @@ extends 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 a2fc34c240..01e0e37fed 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 @@ extends 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 @@ extends 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 @@ extends Gets a PCM Format with the specified parameters. - + static int getPcmFrameSize​(int pcmEncoding, int channelCount) @@ -689,7 +696,7 @@ extends Returns the frame size for audio with channelCount channels in the specified encoding. - + static long getPlayoutDurationForMediaDuration​(long mediaDuration, float speed) @@ -697,14 +704,14 @@ extends 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 @@ extends Returns the specified millisecond time formatted as a string. - + static String[] getSystemLanguageCodes() @@ -721,14 +728,14 @@ extends - + 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 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends Uris, requesting the permission if necessary. - + static boolean maybeRequestReadExternalStoragePermission​(Activity activity, MediaItem... mediaItems) @@ -859,14 +866,14 @@ extends - + 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 @@ extends 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 @@ extends Creates a new array containing original with newElement appended. - + static <T> T[] nullSafeArrayConcatenation​(T[] first, T[] second) @@ -906,7 +913,7 @@ extends 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 @@ extends Copies and optionally truncates an array. - + static <T> T[] nullSafeArrayCopyOfRange​(T[] input, int from, @@ -923,7 +930,7 @@ extends Copies a subset of an array. - + static <T> void nullSafeListToArray​(List<T> list, T[] array) @@ -931,7 +938,7 @@ extends Copies the contents of list into array. - + static long parseXsDateTime​(String value) @@ -939,14 +946,14 @@ extends - + 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 @@ extends Posts the Runnable if the calling thread differs with the Looper of the Handler. - + static boolean readBoolean​(Parcel parcel) @@ -962,7 +969,7 @@ extends - + static byte[] readExactly​(DataSource dataSource, int length) @@ -971,7 +978,7 @@ extends - + static byte[] readToEnd​(DataSource dataSource) @@ -979,14 +986,14 @@ extends - + 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 @@ extends Removes an indexed range from a List. - + static long scaleLargeTimestamp​(long timestamp, long multiplier, @@ -1004,7 +1011,7 @@ extends Scales a large timestamp. - + static long[] scaleLargeTimestamps​(List<Long> timestamps, long multiplier, @@ -1013,7 +1020,7 @@ extends Applies scaleLargeTimestamp(long, long, long) to a list of unscaled timestamps. - + static void scaleLargeTimestampsInPlace​(long[] timestamps, long multiplier, @@ -1022,15 +1029,15 @@ extends 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 @@ extends Splits a string using value.split(regex, -1). - + static String[] splitAtFirst​(String value, String regex) @@ -1046,14 +1053,14 @@ extends 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 @@ extends Context.startService(Intent) otherwise. - + static long subtractWithOverflowDefault​(long x, long y, @@ -1071,7 +1078,7 @@ extends 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 @@ extends 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 @@ extends 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 @@ extends 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 @@ public static <T> T[] castNonNullTypeArray​(@Nullable 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 @@ public static long minValue​(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 @@ public static 
    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 @@ public static 

    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 @@ public static  -
      + + + + +
        +
      • +

        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 e096c9fe09..7d38b8e92e 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); +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 - -
    A builder for ExoFlags instances.
    - - - FileTypes
    Defines common file type constants and helper methods.
    - + FlacConstants
    Defines constants used by the FLAC extractor.
    + +FlagSet + +
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); 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 6aad6f1e74..3c6628e03a 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    @@ -28521,6 +29571,10 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));

    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    +
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    -
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    +
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    -
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    +
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
     
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    -
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    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 47a8fbed67..41bac2c724 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 4bcb39d4f4..c5b1a94e4d 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 2040e675f5..5104fc92a2 100644 --- a/docs/doc/reference/overview-tree.html +++ b/docs/doc/reference/overview-tree.html @@ -313,6 +313,7 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height")); +
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • 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 e07c33ac26..aa8bb32d54 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 061f312715..7ddcf4a956 100644 --- a/docs/doc/reference/serialized-form.html +++ b/docs/doc/reference/serialized-form.html @@ -102,16 +102,12 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
  • -

    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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    • -

      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 @@ $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
    • -

      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 cf4c7f3072..427279dba2 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 e905702b74..b925ec2f1f 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 61cf771815..d696520a2f 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 3c1ac029d8..0e8b7d404b 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 2ef28ed3bb..80dd002825 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 9718306ac7..bc017ae74d 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 58dbb7fe75..de23a32c2b 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 86ead16d51..4756296e2b 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 0000000000..e0f2197176 --- /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 91ef639f1c..061e9cf522 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 fb6824cde4..67c04cbd49 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 95a953d145..d7c6243c3b 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 08d48e9699..9e31bd6ef5 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 @@ import java.nio.ByteBuffer; 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 6b25798e3f..d2f6532fac 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 0efda30b93..49077b8580 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 60ba2e4a36..e1e752ea76 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.Nullable; 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 final class CastPlayer extends BasePlayer { /** * 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 final class CastPlayer extends BasePlayer { 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 final class CastPlayer extends BasePlayer { @Override @Nullable - public ExoPlaybackException getPlayerError() { + public PlaybackException getPlayerError() { return null; } @@ -471,6 +448,21 @@ public final class CastPlayer extends BasePlayer { 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 final class CastPlayer extends BasePlayer { return currentTrackGroups; } + @Deprecated @Override public ImmutableList getCurrentStaticMetadata() { // CastPlayer does not currently support metadata. @@ -561,6 +554,18 @@ public final class CastPlayer extends BasePlayer { 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 @@ public final class CastPlayer extends BasePlayer { // 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 1a03b779f6..584690cb30 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.MediaItem; 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 @@ import java.util.Arrays; /** 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 @@ import java.util.Arrays; 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 4f3f52a5f9..8ff4e37d43 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.CastStatusCodes; 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 @@ import com.google.android.gms.cast.MediaTrack; } /** - * 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 @@ import com.google.android.gms.cast.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 69702ea286..4131f7a641 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 final class DefaultCastOptionsProvider implements OptionsProvider { 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 5fbabb807e..09bf339f0e 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 0a687f50b4..58c6eaf10d 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_CHANGE_MEDIA_ITEMS; 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 class CastPlayerTest { 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 class CastPlayerTest { 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,7 @@ public class CastPlayerTest { } @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}; @@ -1148,42 +1250,100 @@ public class CastPlayerTest { durationsMs, /* positionMs= */ C.TIME_UNSET); - assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)).isFalse(); + 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}; + 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_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 class CastPlayerTest { 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 class CastPlayerTest { @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 class CastPlayerTest { @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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { @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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { @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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { 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 class CastPlayerTest { 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 @@ public class CastPlayerTest { 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 112ad26bba..91248583f8 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 */); -``` -respectively. - -## Choosing between Google Play Services Cronet and Cronet Embedded ## - -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: - -* A negligible increase in the size of your application. -* The Cronet implementation is updated automatically by Google Play Services. - -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. - -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: - -```gradle -implementation 'com.google.android.exoplayer:extension-cronet:2.X.X' -implementation 'org.chromium.net:cronet-embedded:XX.XXXX.XXX' + /* baseDataSourceFactory= */ new CronetDataSource.Factory(...) ); ``` -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 implementations ## -* Your application is likely to be used in markets where Google Play Services is +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. + +### Available implementations ### + +#### Google Play Services #### + +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: + +* 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. + +#### Cronet Embedded #### + +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 d9b2c78507..9a11adbd15 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 967c894c39..71f46621d9 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 @@ package com.google.android.exoplayer2.ext.cronet; 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 class CronetDataSourceContractTest extends DataSourceContractTest { @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 @@ public class CronetDataSourceContractTest extends DataSourceContractTest { 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 e70538d7be..5c5528ed82 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 java.nio.ByteBuffer; 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 @@ import org.chromium.net.UploadDataSink; 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 9b73387fc1..483df638b3 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 @@ package com.google.android.exoplayer2.ext.cronet; 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { * 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { @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 class CronetDataSource extends BaseDataSource implements HttpDataSource { */ 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { */ public Factory setConnectionTimeoutMs(int connectTimeoutMs) { this.connectTimeoutMs = connectTimeoutMs; - internalFallbackFactory.setConnectTimeoutMs(connectTimeoutMs); + if (internalFallbackFactory != null) { + internalFallbackFactory.setConnectTimeoutMs(connectTimeoutMs); + } return this; } @@ -189,7 +243,9 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { */ public Factory setReadTimeoutMs(int readTimeoutMs) { this.readTimeoutMs = readTimeoutMs; - internalFallbackFactory.setReadTimeoutMs(readTimeoutMs); + if (internalFallbackFactory != null) { + internalFallbackFactory.setReadTimeoutMs(readTimeoutMs); + } return this; } @@ -205,7 +261,21 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { */ 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { */ 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { * * @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 class CronetDataSource extends BaseDataSource implements HttpDataSource { @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 class CronetDataSource extends BaseDataSource implements HttpDataSource { } } - /** - * 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { */ 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements 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 class CronetDataSource extends BaseDataSource implements 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { // 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 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { UrlRequest.Builder requestBuilder = cronetEngine .newUrlRequestBuilder(dataSpec.uri.toString(), urlRequestCallback, executor) + .setPriority(requestPriority) .allowDirectExecutor(); // Set the headers. @@ -817,7 +937,11 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { } 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 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { /** * 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 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { * 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 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { } 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 class CronetDataSource extends BaseDataSource implements HttpDataSource { 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 a446fcc299..f10d556f4c 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 @@ import org.chromium.net.CronetEngine; @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 final class CronetDataSourceFactory extends BaseFactory { } @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 @@ public final class CronetDataSourceFactory extends BaseFactory { } 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 de292006ec..8851ac2efe 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 final class CronetEngineWrapper { * @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 final class 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 final class CronetEngineWrapper { /* 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 0000000000..b448c67e2d --- /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 5255163f8e..e2e278ad00 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 @@ package com.google.android.exoplayer2.ext.cronet; 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 static org.mockito.Mockito.when; 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.After; 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 final class CronetDataSourceTest { 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 final class CronetDataSourceTest { 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 final class CronetDataSourceTest { 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 final class CronetDataSourceTest { @Test public void requestOpenFail() { - mockResponseStartFailure(); + mockResponseStartFailure( + /* errorCode= */ Integer.MAX_VALUE, /* cause= */ new IllegalArgumentException()); try { dataSourceUnderTest.open(testDataSpec); @@ -370,9 +377,8 @@ public final class CronetDataSourceTest { @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 final class CronetDataSourceTest { @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 final class CronetDataSourceTest { 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 final class CronetDataSourceTest { 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 final class CronetDataSourceTest { 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 final class CronetDataSourceTest { 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 final class CronetDataSourceTest { @Test public void redirectNoSetCookieFollowsRedirect() throws HttpDataSourceException { - mockSingleRedirectSuccess(); + mockSingleRedirectSuccess(/*responseCode=*/ 300); mockFollowRedirectSuccess(); dataSourceUnderTest.open(testDataSpec); @@ -1232,14 +1238,14 @@ public final class CronetDataSourceTest { 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 final class CronetDataSourceTest { 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 final class CronetDataSourceTest { verify(mockUrlRequestBuilder).allowDirectExecutor(); } + @SuppressWarnings("deprecation") // Tests deprecated fallback functionality. @Test public void factorySetFallbackHttpDataSourceFactory_cronetNotAvailable_usesFallbackFactory() throws HttpDataSourceException, InterruptedException { @@ -1403,10 +1470,11 @@ public final class CronetDataSourceTest { 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 final class CronetDataSourceTest { .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 final class CronetDataSourceTest { assertThat(dataSourceUnderTest).isInstanceOf(DefaultHttpDataSource.class); } + @SuppressWarnings("deprecation") // Tests deprecated fallback functionality. @Test public void factory_noFallbackFactoryCronetNotAvailable_delegateDefaultRequestPropertiesToInternalFallbackFactoryAfterCreation() @@ -1512,14 +1581,14 @@ public final class CronetDataSourceTest { .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 @@ public final class CronetDataSourceTest { .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 @@ public final class CronetDataSourceTest { dataSourceUnderTest.urlRequestCallback.onFailed( mockUrlRequest, createUrlResponseInfo(500), // statusCode - mockNetworkException); + createNetworkException( + /* errorCode= */ Integer.MAX_VALUE, + /* cause= */ new IllegalArgumentException())); return null; }) .when(mockUrlRequest) @@ -1661,4 +1732,23 @@ public final class CronetDataSourceTest { 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 eac96a9a31..1feeffeef9 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 @@ import java.util.List; 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 878476d1a1..3991f53a38 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 final class FfmpegAudioRenderer extends DecoderAudioRenderer #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 a52f8088b3..c2cfc4547d 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 android.os.Looper; 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 @@ public class FlacPlaybackTest { 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 class FlacPlaybackTest { } @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 af4e571024..c4e5e4e710 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 com.google.android.exoplayer2.util.Util; 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 @@ import java.nio.ByteBuffer; 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 @@ import java.nio.ByteBuffer; } } - /** - * 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 @@ import java.nio.ByteBuffer; 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 99e74d64bb..715489ccde 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 final class FlacExtractor implements Extractor { } @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 @@ public final class FlacExtractor implements Extractor { @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 8a2b14d366..6ce93ef56d 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 final class FlacLibrary { 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 4fea5ffa53..7b74d3bfd7 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 final class LibflacAudioRenderer extends DecoderAudioRenderer - #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 041ca09db4..0fc6f54285 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 class GvrAudioProcessor implements AudioProcessor { } /** - * 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 class GvrAudioProcessor implements AudioProcessor { 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 class GvrAudioProcessor implements AudioProcessor { } @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 @@ public class GvrAudioProcessor implements AudioProcessor { gvrAudioSurround = null; } } - } diff --git a/extensions/ima/build.gradle b/extensions/ima/build.gradle index 80fcab9587..ad46882f7c 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 6ddc317274..d2f70d5e1b 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 final class ImaPlaybackTest { @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 6690fa95ec..0e8b246100 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.ContentProgressProvider; 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 @@ import java.util.Map; /** 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 @@ import java.util.Map; 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 @@ import java.util.Map; } } - // Player.EventListener implementation. + // Player.Listener implementation. @Override public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) { @@ -514,7 +514,7 @@ import java.util.Map; } @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 @@ import java.util.Map; } // 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 @@ import java.util.Map; 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 @@ import java.util.Map; 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 @@ import java.util.Map; } } 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 @@ import java.util.Map; // 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 @@ import java.util.Map; 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 @@ import java.util.Map; // 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 @@ import java.util.Map; 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 @@ import java.util.Map; 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 @@ import java.util.Map; 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 @@ import java.util.Map; } } - 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 72cae676af..f77a5a0aa6 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 final class ImaAdsLoader implements Player.Listener, AdsLoader { // 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 6b62b38e4d..ee889ab349 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.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.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.Mock; 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 final class ImaAdsLoaderTest { 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 final class ImaAdsLoaderTest { 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 f2fc3279b8..f38fe14f20 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 androidx.leanback.media.SurfaceHolderGlueHost; 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 final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab } /** - * @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 final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab * @param errorMessageProvider The {@link ErrorMessageProvider}. */ public void setErrorMessageProvider( - @Nullable ErrorMessageProvider errorMessageProvider) { + @Nullable ErrorMessageProvider errorMessageProvider) { this.errorMessageProvider = errorMessageProvider; } @@ -148,7 +134,8 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab @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 final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab @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 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab } } - @SuppressWarnings("nullness:argument.type.incompatible") + @SuppressWarnings("nullness:argument") private static void removeSurfaceHolderCallback(SurfaceHolderGlueHost surfaceHolderGlueHost) { surfaceHolderGlueHost.setSurfaceHolderCallback(null); } @@ -265,7 +250,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab setVideoSurface(null); } - // Player.EventListener implementation. + // Player.Listener implementation. @Override public void onPlaybackStateChanged(@Player.State int playbackState) { @@ -273,14 +258,20 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab } @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 final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab 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 a995bfdb5b..3c202ba375 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 @@ import org.junit.rules.ExternalResource; } @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 d4e996caa2..d8e29cc79f 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.filters.SmallTest; 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 class SessionPlayerConnectorTest { 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 class SessionPlayerConnectorTest { } } + @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 class SessionPlayerConnectorTest { .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 ea29ccbe53..4b25db5643 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 androidx.media2.common.SessionPlayer; 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 @@ import java.util.List; } } + /** + * @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 @@ import java.util.List; } 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 @@ import java.util.List; 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 @@ import java.util.List; } 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 @@ import java.util.List; 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 @@ import java.util.List; 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 @@ import java.util.List; 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 @@ import java.util.List; 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 @@ import java.util.List; } 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 @@ import java.util.List; 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 @@ import java.util.List; } @Override - public void onPlayerError(ExoPlaybackException error) { + public void onPlayerError(PlaybackException error) { updateSessionPlayerState(); } @@ -616,8 +638,6 @@ import java.util.List; 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 4b161a7345..c718efa85d 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 @@ import java.util.concurrent.TimeoutException; // 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 516ec20b3b..b905464ee8 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 final class SessionCallbackBuilder { * @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 e51964b648..e2eb6d1134 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.MediaItem; 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 final class SessionPlayerConnector extends SessionPlayer { } /** - * 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 final class SessionPlayerConnector extends SessionPlayer { } /** - * 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 @@ public final class SessionPlayerConnector extends SessionPlayer { // 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 873e35cc25..87b52f3598 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 @@ import com.google.android.exoplayer2.audio.AudioAttributes; } } - 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 f806a579be..3c461c8853 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 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.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.Collections; 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 final class MediaSessionConnector { */ boolean onCommand( Player player, - ControlDispatcher controlDispatcher, + @Deprecated ControlDispatcher controlDispatcher, String command, @Nullable Bundle extras, @Nullable ResultReceiver cb); @@ -294,26 +296,32 @@ public final class MediaSessionConnector { * 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 final class MediaSessionConnector { * 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 final class MediaSessionConnector { * 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 final class MediaSessionConnector { * @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 final class MediaSessionConnector { 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 final class MediaSessionConnector { @Nullable private MediaButtonEventHandler mediaButtonEventHandler; private long enabledPlaybackActions; + private boolean metadataDeduplicationEnabled; + private boolean dispatchUnsupportedActionsEnabled; /** * Creates an instance. @@ -504,10 +560,11 @@ public final class MediaSessionConnector { } /** - * 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 final class MediaSessionConnector { } } - /** - * @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 final class MediaSessionConnector { } } + /** + * 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 class MediaSessionConnector { 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 class MediaSessionConnector { 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 @@ public final class MediaSessionConnector { } 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 @@ public final class MediaSessionConnector { @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 @@ public final class MediaSessionConnector { 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 final class MediaSessionConnector { @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 87b9447f7c..99c85b2353 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 final class RepeatModeActionProvider implements MediaSessionConnector.Cus @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 final class RepeatModeActionProvider implements MediaSessionConnector.Cus 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 cab16744b9..f6af25d188 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 final class TimelineQueueEditor /** * 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 final class TimelineQueueEditor 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 final class TimelineQueueEditor @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 4a27ca9d93..2b33d9b989 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 abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu /** * 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 abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu 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 abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu } @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 abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu } @Override - public void onSkipToNext(Player player, ControlDispatcher controlDispatcher) { + public void onSkipToNext(Player player, @Deprecated ControlDispatcher controlDispatcher) { controlDispatcher.dispatchNext(player); } @@ -170,7 +171,7 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu @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 2f9893fe3b..2aad867e79 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 758eb646f6..96424b4380 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 0b881955a1..9d5d1cc5a0 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 android.net.Uri; 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.HttpUtil; 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 class OkHttpDataSource extends BaseDataSource implements HttpDataSource { 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 class OkHttpDataSource extends BaseDataSource implements HttpDataSource { } 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 class OkHttpDataSource extends BaseDataSource implements HttpDataSource { 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 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { @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 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { * 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 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { 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 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { } 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 5b6a31ca92..05780cbe3a 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 final class OkHttpDataSourceFactory extends BaseFactory { 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 9cb606a718..d5d1adf899 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 android.os.Looper; 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 @@ public class OpusPlaybackTest { 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 class OpusPlaybackTest { } @Override - public void onPlayerError(ExoPlaybackException error) { + public void onPlayerError(PlaybackException error) { playbackException = error; } @@ -121,7 +121,5 @@ public class OpusPlaybackTest { 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 8d9cfea763..e9563b9af1 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 71ba1db106..47b1cef657 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 final class OpusLibrary { 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 final class OpusLibrary { } 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 a2515be7f6..96c2838039 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 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 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 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 a34341692b..99e9d25e8e 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 587e310d64..8093b4d275 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.ExoPlayerLibraryInfo; 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 final class RtmpDataSource extends BaseDataSource { } @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 final class RtmpDataSource extends BaseDataSource { 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 167a4175d7..7d05adb18d 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 @@ package com.google.android.exoplayer2.ext.rtmp; 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 final class RtmpDataSourceFactory implements DataSource.Factory { } return dataSource; } - } diff --git a/extensions/vp9/README.md b/extensions/vp9/README.md index 30b7a252d0..84f3f01326 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 6e473eb21e..56fca12d19 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 d7a19f1662..b9d841ccf8 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 android.os.Looper; 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 @@ public class VpxPlaybackTest { 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 class VpxPlaybackTest { } @Override - public void onPlayerError(ExoPlaybackException error) { + public void onPlayerError(PlaybackException error) { playbackException = error; } @@ -157,5 +157,4 @@ public class VpxPlaybackTest { } } } - } 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 021ce3a946..7e8eedb210 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 @@ public final class VpxDecoder 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 @@ public final class VpxDecoder 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 @@ public final class VpxDecoder 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 339ec021c6..8325265685 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 final class VpxLibrary { 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 final class VpxLibrary { 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 final class VpxLibrary { } private static native String vpxGetVersion(); - private static native String vpxGetBuildConfig(); - public static native boolean vpxIsSecureDecodeSupported(); + private static native String vpxGetBuildConfig(); + + 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 6d36164d1d..0000000000 --- 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 1fc0f9d56e..3f4c89dc7b 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 297016aec1..226168bb1d 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 8efe8c9f90..76c4be41e9 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 d1d0d86f42..bdfe7a00f3 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 57550d589b..74b5760ca7 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 abstract class BasePlayer implements Player { 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); @@ -127,31 +122,96 @@ public abstract class BasePlayer implements Player { } @Override - public final boolean hasPrevious() { - return getPreviousWindowIndex() != C.INDEX_UNSET; + 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 getNextWindowIndex() != C.INDEX_UNSET; + 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 abstract class BasePlayer implements Player { 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 abstract class BasePlayer implements Player { : 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 eba6c0cfcd..b5df4c4e1c 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class C { /** Indicates that a buffer should be decoded but not rendered. */ public static final int BUFFER_FLAG_DECODE_ONLY = 1 << 31; // 0x80000000 - // LINT.IfChange /** * Video decoder output modes. Possible modes are {@link #VIDEO_OUTPUT_MODE_NONE}, {@link * #VIDEO_OUTPUT_MODE_YUV} and {@link #VIDEO_OUTPUT_MODE_SURFACE_YUV}. @@ -550,10 +473,6 @@ public final class C { public static final int VIDEO_OUTPUT_MODE_YUV = 0; /** Video decoder output mode that renders 4:2:0 YUV planes directly to a surface. */ public static final int VIDEO_OUTPUT_MODE_SURFACE_YUV = 1; - // LINT.ThenChange( - // ../../../../../../../../../../../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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 @@ public final class 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 final class C { } /** - * 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 final class C { 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 4e9b20acf3..a24131e956 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 @@ package com.google.android.exoplayer2; 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 03f03d5903..b20daebefb 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 @@ package com.google.android.exoplayer2; 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 class DefaultControlDispatcher implements ControlDispatcher { public DefaultControlDispatcher(long fastForwardIncrementMs, long rewindIncrementMs) { this.fastForwardIncrementMs = fastForwardIncrementMs; this.rewindIncrementMs = rewindIncrementMs; - window = new Timeline.Window(); + rewindAndFastForwardIncrementsSet = true; } @Override @@ -72,44 +67,21 @@ public class DefaultControlDispatcher implements ControlDispatcher { @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 class DefaultControlDispatcher implements ControlDispatcher { @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 class DefaultControlDispatcher implements ControlDispatcher { @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 @@ public class DefaultControlDispatcher implements ControlDispatcher { 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 68bb899a73..198ec23817 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 @@ import java.util.HashSet; /** 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 final class ExoPlayerLibraryInfo { 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 d4eb5e13d2..eba199299e 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 @@ import java.util.UUID; * 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 @@ import java.util.UUID; *
      • {@link #metadata} *
      * - *

      Fields relevant to container formats

      + *

      Fields relevant to container formats

      * *
        *
      • {@link #containerMimeType} @@ -70,7 +70,7 @@ import java.util.UUID; * href="#audio-formats">audio and text formats. *
      * - *

      Fields relevant to sample formats

      + *

      Fields relevant to sample formats

      * *
        *
      • {@link #sampleMimeType} @@ -83,7 +83,7 @@ import java.util.UUID; * href="#text-formats">text formats. *
      * - *

      Fields relevant to video formats

      + *

      Fields relevant to video formats

      * *
        *
      • {@link #width} @@ -96,7 +96,7 @@ import java.util.UUID; *
      • {@link #colorInfo} *
      * - *

      Fields relevant to audio formats

      + *

      Fields relevant to audio formats

      * *
        *
      • {@link #channelCount} @@ -106,7 +106,7 @@ import java.util.UUID; *
      • {@link #encoderPadding} *
      * - *

      Fields relevant to text formats

      + *

      Fields relevant to text formats

      * *
        *
      • {@link #accessibilityChannel} @@ -686,8 +686,8 @@ public final class Format implements Parcelable { */ 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 final class Format implements Parcelable { // 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 final class Format implements Parcelable { // 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 final class Format implements Parcelable { // 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 final class Format implements Parcelable { .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 final class Format implements Parcelable { .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 final class Format implements Parcelable { dest.writeInt(accessibilityChannel); } - public static final Creator CREATOR = new Creator() { + public static final Creator CREATOR = + new Creator() { - @Override - public Format createFromParcel(Parcel in) { - return new Format(in); - } + @Override + public Format createFromParcel(Parcel in) { + return new Format(in); + } - @Override - public Format[] newArray(int size) { - return new Format[size]; - } - - }; + @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 0000000000..7112efa8a2 --- /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 745e86983f..71f57dec82 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 @@ package com.google.android.exoplayer2; */ 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 final class IllegalSeekPositionException extends IllegalStateException { 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 bb92bc779e..e8373532a1 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 final class MediaItem implements Bundleable { 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 @@ public final class MediaItem implements Bundleable { */ 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 b299b86e52..e76edee173 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 @@ package com.google.android.exoplayer2; 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 final class MediaMetadata implements Bundleable { @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 @@ public final class MediaMetadata implements Bundleable { 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 final class MediaMetadata implements Bundleable { 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 final class MediaMetadata implements Bundleable { 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 final class MediaMetadata implements Bundleable { @Documented @Retention(RetentionPolicy.SOURCE) @IntDef({ + FOLDER_TYPE_NONE, FOLDER_TYPE_MIXED, FOLDER_TYPE_TITLES, FOLDER_TYPE_ALBUMS, @@ -255,6 +410,8 @@ public final class MediaMetadata implements Bundleable { }) 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 final class MediaMetadata implements Bundleable { /** 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 final class MediaMetadata implements Bundleable { @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 final class MediaMetadata implements Bundleable { @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 @@ public final class MediaMetadata implements Bundleable { 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 final class MediaMetadata implements Bundleable { && 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 final class MediaMetadata implements Bundleable { 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 final class MediaMetadata implements Bundleable { 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 final class MediaMetadata implements Bundleable { 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 final class MediaMetadata implements Bundleable { 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 final class MediaMetadata implements Bundleable { 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 @@ public final class MediaMetadata implements Bundleable { .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 @@ public final class MediaMetadata implements Bundleable { 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 716eceda94..1e6c3a88f2 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) { + 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 0000000000..335dcf2612 --- /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 3ef38c8520..0000000000 --- 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 0bb973d4ef..dfa80d40b4 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.metadata.MetadataOutput; 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 com.google.common.base.Objects; 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 @@ public interface Player { */ 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 @@ public interface Player { 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 @@ public interface Player { */ 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 @@ public interface Player { *

        {@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 @@ public interface Player { *

        {@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 @@ public interface Player { */ 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 @@ public interface Player { *

        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 @@ public interface Player { 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 interface Player { } /** - * 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 @@ public interface Player { * *

        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 interface Player { 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 interface Player { /** 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 interface Player { 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 @@ public interface Player { 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 @@ public interface Player { 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 @@ public interface Player { @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 @@ public interface Player { default void onMediaMetadataChanged(MediaMetadata mediaMetadata) {} @Override - default void onStaticMetadataChanged(List metadataList) {} + default void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {} } /** @@ -907,15 +1094,15 @@ public interface Player { }) @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 @@ public interface Player { @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 @@ public interface Player { @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 @@ public interface Player { /** * 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 @@ public interface Player { 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 @@ public interface Player { 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 @@ public interface Player { @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 @@ public interface Player { /** 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 @@ public interface Player { 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 @@ public 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 {@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 @@ public interface Player { * *

        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 @@ public interface Player { * 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 @@ public interface Player { /** * 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 @@ public interface Player { */ 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 @@ public interface Player { * 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 @@ public interface Player { * 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 @@ public interface Player { 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 @@ public interface Player { * 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 @@ public interface Player { 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 @@ public interface Player { 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 @@ public interface Player { */ 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 10e91fc22f..5e9ff6a65d 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 @@ import java.util.List; * *

        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 @@ import java.util.List; * 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 @@ import java.util.List; * (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 @@ import java.util.List; * 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 @@ import java.util.List; * 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 @@ import java.util.List; * 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 @@ import java.util.List; * 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 abstract class Timeline 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline implements Bundleable { * 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 abstract class Timeline implements Bundleable { * 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 abstract class Timeline implements Bundleable { * 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 abstract class Timeline implements Bundleable { } /** - * 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline implements Bundleable { } }; - /** - * 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline implements Bundleable { 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 abstract class Timeline implements Bundleable { *

        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 abstract class Timeline implements Bundleable { 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 @@ public abstract class Timeline implements Bundleable { * 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 abstract class Timeline implements Bundleable { } @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 abstract class Timeline implements Bundleable { } @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 c97893b428..2684273b2e 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 final class AacUtil { 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 final class AacUtil { 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 final class AacUtil { // 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 @@ public final class AacUtil { } 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 8cbd53d1b7..dbb234c5d8 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 final class Ac3Util { * #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 @@ public final class Ac3Util { 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 @@ public final class Ac3Util { */ 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 final class Ac3Util { } 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 final class Ac3Util { 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 @@ public final class Ac3Util { } 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 b91e642d14..f503ab53c4 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 final class AudioAttributes implements Bundleable { 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 final class AudioAttributes implements Bundleable { 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 3a0f0e093d..1a741d47d5 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 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 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 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 final class DtsUtil { 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 @@ public final class DtsUtil { } 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 6d74bf820e..71ea215d2c 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 @@ import com.google.android.exoplayer2.C; /** 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 abstract class Buffer { /** * 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 abstract class Buffer { 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 80486feb91..b4e04afe42 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 final class 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 @@ public final class CryptoInfo { 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 ff295657e1..71b3a68d19 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 class DecoderInputBuffer extends Buffer { 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 class DecoderInputBuffer extends Buffer { */ 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 class DecoderInputBuffer extends Buffer { 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 4113f4c27d..5c366ef9e2 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 final class DrmInitData implements Comparator, Parcelable { 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 final class DrmInitData implements Comparator, Parcelable { 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 final class DrmInitData implements Comparator, Parcelable { @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 final class DrmInitData implements Comparator, Parcelable { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public DrmInitData createFromParcel(Parcel in) { - return new DrmInitData(in); - } + @Override + public DrmInitData createFromParcel(Parcel in) { + return new DrmInitData(in); + } - @Override - public DrmInitData[] newArray(int size) { - return new DrmInitData[size]; - } - - }; + @Override + public DrmInitData[] newArray(int size) { + return new DrmInitData[size]; + } + }; // Internal methods. @@ -252,9 +246,7 @@ public final class DrmInitData implements Comparator, Parcelable { return false; } - /** - * Scheme initialization data. - */ + /** Scheme initialization data. */ public static final class SchemeData implements Parcelable { // Lazily initialized hashcode. @@ -324,9 +316,7 @@ public final class DrmInitData implements Comparator, Parcelable { 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 final class DrmInitData implements Comparator, Parcelable { 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 01ae340609..ffa837deff 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 @@ public final class Metadata implements Parcelable { 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 final class Metadata implements Parcelable { } } - /** - * 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 55e0b75f71..0ce9eb616b 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 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; 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 0dd46bae22..8f8046d7e2 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 final class EventMessage implements Metadata.Entry { 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 ce134614ad..8d62be52c6 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 static com.google.android.exoplayer2.util.Util.castNonNull; 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 final class PictureFrame implements Metadata.Entry { 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 9f44cdf393..3ab60541a9 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 static com.google.android.exoplayer2.util.Util.castNonNull; 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 final class VorbisComment implements Metadata.Entry { 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 25efeba076..84d426c6b9 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 final class ApicFrame extends Id3Frame { @Override public void populateMediaMetadata(MediaMetadata.Builder builder) { - builder.setArtworkData(pictureData); + builder.maybeSetArtworkData(pictureData, pictureType); } @Override @@ -65,7 +65,8 @@ public final class ApicFrame extends Id3Frame { 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 final class ApicFrame extends Id3Frame { 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 995418f3b4..39305404cf 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 final class BinaryFrame extends Id3Frame { 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 120b9269f1..e759a73aac 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 final class ChapterFrame extends Id3Frame { } } - /** - * 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 final class ChapterFrame extends Id3Frame { return 0; } - public static final Creator CREATOR = new Creator() { + 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]; - } - - }; + @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 5e662c388c..ee7bcd397e 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 final class ChapterTocFrame extends Id3Frame { } } - /** - * 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 final class ChapterTocFrame extends Id3Frame { } } - 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 8b2d14444d..5d441e782f 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 final class CommentFrame extends Id3Frame { 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 final class CommentFrame extends Id3Frame { 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 c0c8ad631f..2c609db8d5 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 final class GeobFrame extends Id3Frame { 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 final class GeobFrame extends Id3Frame { 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 5bd0e1e3e8..0d97cef846 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 @@ import java.util.Locale; /** 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 final class Id3Decoder extends SimpleMetadataDecoder { * @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 final class Id3Decoder extends SimpleMetadataDecoder { /** 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { } 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { } /** - * 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { } } - 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 @@ public final class Id3Decoder extends SimpleMetadataDecoder { 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 final class Id3Decoder extends SimpleMetadataDecoder { 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 24e1188879..e54de84f58 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 @@ import com.google.android.exoplayer2.metadata.Metadata; /** 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 abstract class Id3Frame implements Metadata.Entry { 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 773e49e846..567785ac16 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 final class PrivFrame extends Id3Frame { dest.writeByteArray(privateData); } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + 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]; - } - - }; + @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 a8afe719b8..7bab697331 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 android.os.Parcelable; 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 final class TextInformationFrame extends Id3Frame { 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 final class TextInformationFrame extends Id3Frame { 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 d9b73ab011..6648d852fa 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 final class UrlLinkFrame extends Id3Frame { 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 final class UrlLinkFrame extends Id3Frame { 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 2df780ce93..0888f3fa96 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 5b207492d9..cc6e6f1332 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 final class AdPlaybackState 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 final class AdPlaybackState implements Bundleable { 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 final class AdPlaybackState implements Bundleable { 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 final class AdPlaybackState implements Bundleable { 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 final class AdPlaybackState implements Bundleable { @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 final class AdPlaybackState implements Bundleable { 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 final class AdPlaybackState implements Bundleable { } 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 final class AdPlaybackState implements Bundleable { 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 final class AdPlaybackState implements Bundleable { 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 @@ public final class AdPlaybackState implements Bundleable { @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 final class AdPlaybackState implements Bundleable { 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 @@ public final class AdPlaybackState implements Bundleable { @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 @@ public final class AdPlaybackState implements Bundleable { 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 @@ public final class AdPlaybackState implements Bundleable { /** 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 @@ public final class AdPlaybackState implements Bundleable { 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 @@ public final class AdPlaybackState implements Bundleable { 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 final class AdPlaybackState implements Bundleable { } // 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 final class AdPlaybackState implements Bundleable { @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 final class AdPlaybackState implements Bundleable { */ @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 final class AdPlaybackState implements Bundleable { return this; } else { return new AdPlaybackState( - adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs); + adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount); } } @@ -536,10 +708,69 @@ public final class AdPlaybackState implements Bundleable { 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 public boolean equals(@Nullable Object o) { if (this == o) { @@ -553,7 +784,7 @@ public final class AdPlaybackState implements Bundleable { && 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 final class AdPlaybackState implements Bundleable { 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 final class AdPlaybackState implements Bundleable { 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 @@ public final class AdPlaybackState implements Bundleable { // 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 @@ public final class AdPlaybackState implements Bundleable { @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 @@ public final class AdPlaybackState implements Bundleable { @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 final class AdPlaybackState implements Bundleable { 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 final class AdPlaybackState implements Bundleable { 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 @@ public final class AdPlaybackState implements Bundleable { 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 7735b808de..66ab2f3682 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 @@ package com.google.android.exoplayer2.text; 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 final class Cue { 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 final class Cue { * * @see Cue#text */ + @Pure @Nullable public CharSequence getText() { return text; @@ -586,6 +634,7 @@ public final class Cue { * * @see Cue#bitmap */ + @Pure @Nullable public Bitmap getBitmap() { return bitmap; @@ -608,6 +657,7 @@ public final class Cue { * * @see Cue#textAlignment */ + @Pure @Nullable public Alignment getTextAlignment() { return textAlignment; @@ -644,6 +694,7 @@ public final class Cue { * * @see Cue#line */ + @Pure public float getLine() { return line; } @@ -653,6 +704,7 @@ public final class Cue { * * @see Cue#lineType */ + @Pure @LineType public int getLineType() { return lineType; @@ -673,6 +725,7 @@ public final class Cue { * * @see Cue#lineAnchor */ + @Pure @AnchorType public int getLineAnchor() { return lineAnchor; @@ -695,6 +748,7 @@ public final class Cue { * * @see Cue#position */ + @Pure public float getPosition() { return position; } @@ -714,6 +768,7 @@ public final class Cue { * * @see Cue#positionAnchor */ + @Pure @AnchorType public int getPositionAnchor() { return positionAnchor; @@ -736,6 +791,7 @@ public final class Cue { * * @see Cue#textSizeType */ + @Pure @TextSizeType public int getTextSizeType() { return textSizeType; @@ -746,6 +802,7 @@ public final class Cue { * * @see Cue#textSize */ + @Pure public float getTextSize() { return textSize; } @@ -767,6 +824,7 @@ public final class Cue { * * @see Cue#size */ + @Pure public float getSize() { return size; } @@ -786,6 +844,7 @@ public final class Cue { * * @see Cue#bitmapHeight */ + @Pure public float getBitmapHeight() { return bitmapHeight; } @@ -824,6 +883,7 @@ public final class Cue { * * @see Cue#windowColor */ + @Pure @ColorInt public int getWindowColor() { return windowColor; @@ -850,6 +910,7 @@ public final class Cue { * * @see Cue#verticalType */ + @Pure @VerticalType public int getVerticalType() { return verticalType; @@ -877,4 +938,138 @@ public final class Cue { 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 0000000000..bb8fce5fa4 --- /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 eeddc9984e..4b96a3ddfb 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 c157002809..c6ac0a261a 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 @@ import java.util.Map; /** 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 @@ public interface DataSource extends DataReader { * * @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 c3ccdb88d9..073f0a46a9 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 final class DataSourceException extends IOException { /** * 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}. */ - public static final int POSITION_OUT_OF_RANGE = 0; + @Deprecated + public static final int POSITION_OUT_OF_RANGE = + PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE; /** - * The reason of this {@link DataSourceException}. It can only be {@link #POSITION_OUT_OF_RANGE}. + * The reason of this {@link DataSourceException}, should be one of the {@code ERROR_CODE_IO_*} in + * {@link PlaybackException.ErrorCode}. */ - public final int reason; + @PlaybackException.ErrorCode public final int reason; /** * Constructs a DataSourceException. * - * @param reason Reason of the error. It can only be {@link #POSITION_OUT_OF_RANGE}. + * @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(@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 DataSourceException(@Nullable Throwable cause, @PlaybackException.ErrorCode int reason) { + super(cause); + this.reason = reason; + } + + /** + * 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 DataSourceException(@Nullable String message, @PlaybackException.ErrorCode int reason) { + super(message); + this.reason = reason; + } + + /** + * Constructs a DataSourceException. + * + * @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( + @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 d484779d36..dde0835517 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 final class DataSpec { /** 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 88193c2646..d2c6b5e993 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 android.net.Uri; 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.InterruptedIOException; 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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou private int connectTimeoutMs; private int readTimeoutMs; private boolean allowCrossProtocolRedirects; + private boolean keepPostFor302Redirects; /** Creates an instance. */ public Factory() { @@ -175,6 +176,15 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou 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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou readTimeoutMs, allowCrossProtocolRedirects, defaultRequestProperties, - contentTypePredicate); + contentTypePredicate, + keepPostFor302Redirects); if (transferListener != null) { dataSource.addTransferListener(transferListener); } @@ -194,9 +205,7 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou /** 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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou @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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou readTimeoutMillis, allowCrossProtocolRedirects, defaultRequestProperties, - /* contentTypePredicate= */ null); + /* contentTypePredicate= */ null, + /* keepPostFor302Redirects= */ false); } private DefaultHttpDataSource( @@ -271,7 +282,8 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou 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 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou this.defaultRequestProperties = defaultRequestProperties; this.contentTypePredicate = contentTypePredicate; this.requestProperties = new RequestProperties(); + this.keepPostFor302Redirects = keepPostFor302Redirects; } /** @@ -325,9 +338,7 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou 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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou 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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou 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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou 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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou } } 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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou 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 class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou } } - /** - * 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 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou 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 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou 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 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou || 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 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou * * @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); + 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); } - // 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 + ")"); - // } return url; } @@ -649,37 +694,42 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou * 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 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou } } - /** - * 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 dbaa686066..150d983348 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 @@ package com.google.android.exoplayer2.upstream; 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 @@ import java.util.Map; /** 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 @@ public interface HttpDataSource extends DataSource { } /** - * 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 interface HttpDataSource extends DataSource { requestProperties.remove(name); } - /** - * Clears all request properties. - */ + /** Clears all request properties. */ public synchronized void clear() { requestPropertiesSnapshot = null; requestProperties.clear(); @@ -191,51 +190,176 @@ public interface HttpDataSource extends DataSource { && !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; + /** + * 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; /** - * The {@link DataSpec} associated with the current connection. + * @deprecated Use {@link #HttpDataSourceException(DataSpec, int, int) + * HttpDataSourceException(DataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, int)}. */ - public final DataSpec dataSpec; - + @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.dataSpec = dataSpec; - this.type = type; + this(message, dataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, type); } - public HttpDataSourceException(IOException cause, DataSpec dataSpec, @Type int type) { - super(cause); - this.dataSpec = dataSpec; - this.type = type; - } - - public HttpDataSourceException(String message, IOException cause, DataSpec dataSpec, + /** + * 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, cause); + 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) { + 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; + } + + /** + * @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, 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 interface HttpDataSource extends DataSource { + " 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 interface HttpDataSource extends DataSource { */ 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 interface HttpDataSource extends DataSource { 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 interface HttpDataSource extends DataSource { this( responseCode, responseMessage, + /* cause= */ null, headerFields, dataSpec, /* responseBody= */ Util.EMPTY_BYTE_ARRAY); @@ -324,16 +451,21 @@ public interface HttpDataSource extends DataSource { 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 interface HttpDataSource extends DataSource { 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 interface HttpDataSource extends DataSource { */ 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 a8971e71a4..806efca73f 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 0bb65e55e0..64496358cf 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 final class Assertions { * @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 final class Assertions { * @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 final class Assertions { * @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 final class Assertions { * @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 final class Assertions { * @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 final class Assertions { * @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 final class Assertions { 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 1c1e139d80..fcf07a8901 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 final class BundleUtil { } // 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 @@ public final class BundleUtil { } // 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 0000000000..adc9514f7d --- /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 8ecb2ab8ec..b21e5773e6 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 @@ import androidx.annotation.Nullable; */ 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 46c9e486df..6322114b90 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 @@ import androidx.annotation.Nullable; * *

        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 final class ExoFlags { } /** - * 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 final class ExoFlags { } /** - * 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 final class ExoFlags { 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 fe220b1946..7f2ce9759a 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 final class ListenerSet { * 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 final class ListenerSet { * 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 @@ public final class 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 final class ListenerSet { } } + /** 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 final class ListenerSet { 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 final class ListenerSet { 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 @@ public final class ListenerSet { @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 final class ListenerSet { 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 fd1b74ca6e..1b3a080995 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 @@ public final class 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 d6a1733697..a9709dff70 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 final class 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 final class LongArray { 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 final class LongArray { 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 066cdc9ea4..a3bf921172 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 final class MimeTypes { 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 d6d4a7aa01..1fd44011e0 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 final class NalUnitUtil { 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 final class NalUnitUtil { /** 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 final class NalUnitUtil { 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 final class NalUnitUtil { 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 final class NalUnitUtil { /** * 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 final class NalUnitUtil { */ 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 final class NalUnitUtil { 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 final class NalUnitUtil { /** * 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 final class NalUnitUtil { * 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 @@ public final class NalUnitUtil { 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 c14eee6f88..7efaa42c7a 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 final class ParsableBitArray { 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 final class ParsableBitArray { assertValidOffset(); } - /** - * Skips a single bit. - */ + /** Skips a single bit. */ public void skipBit() { if (++bitOffset == 8) { bitOffset = 0; @@ -344,8 +338,7 @@ public final class ParsableBitArray { 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 dff16d39f1..79913d2aa9 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 final class ParsableByteArray { return limit - position; } - /** - * Returns the limit. - */ + /** Returns the limit. */ public int limit() { return limit; } @@ -137,9 +135,7 @@ public final class ParsableByteArray { 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 final class ParsableByteArray { } /** - * 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 final class ParsableByteArray { 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 final class ParsableByteArray { | (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 final class ParsableByteArray { | (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 final class ParsableByteArray { | (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 final class ParsableByteArray { | (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 final class ParsableByteArray { | (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 final class ParsableByteArray { | (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 final class ParsableByteArray { 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 final class ParsableByteArray { 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 final class ParsableByteArray { 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 6738ed7b0e..50810bc6a0 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 final class ParsableNalUnitBitArray { assertValidOffset(); } - /** - * Skips a single bit. - */ + /** Skips a single bit. */ public void skipBit() { if (++bitOffset == 8) { bitOffset = 0; @@ -198,14 +196,16 @@ public final class ParsableNalUnitBitArray { } 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 0acc430b0c..26c586f9a4 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 @@ import java.lang.annotation.RetentionPolicy; /** 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 @@ public final class 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 a76cf9b512..1f5da87a59 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 androidx.annotation.GuardedBy; 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 DO_NOT_OFFSET = Long.MAX_VALUE; + 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 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 final class TimestampAdjuster { /** * 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 final class TimestampAdjuster { 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 final class TimestampAdjuster { 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 df6ffd557c..87d63fcd06 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 @@ public final class TraceUtil { 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 23ecc38e05..e222e83ffb 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 final class Util { * *

        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 final class Util { * @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 final class Util { * @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 final class Util { * @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 final class Util { * 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 final class Util { /** * 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 final class Util { * @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 final class Util { */ // 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 final class Util { } 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 final class Util { 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 final class Util { /** * 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 final class Util { 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 final class Util { } 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 final class Util { } } - /** - * 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 final class Util { } } - /** - * 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 final class Util { } } - /** - * 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 final class Util { * 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 final class Util { } /** - * 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 final class Util { */ 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 final class Util { 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 final class Util { 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 975b66f093..a6c5577749 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 final class AvcConfig { @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 final class AvcConfig { 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 @@ public final class AvcConfig { 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 6d66c91f6c..38fe968668 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.C; 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 final class ColorInfo implements Parcelable { @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 c058457665..567485ba92 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 final class HevcConfig { 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 final class HevcConfig { 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 @@ public final class 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 1721ce807a..d47c58fed8 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 class ExoPlaybackExceptionTest { /* 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 @@ public class ExoPlaybackExceptionTest { && 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 0000000000..38bf115135 --- /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 47aa1a6833..769758647e 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 static com.google.common.truth.Truth.assertThat; 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 class MediaMetadataTest { 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 class MediaMetadataTest { @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 class MediaMetadataTest { .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 class MediaMetadataTest { 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 0000000000..b963c847c7 --- /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 2bd02446da..5d3aad24b2 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 final class EventMessageDecoderTest { 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 9a47b81d44..536392f85e 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 final class EventMessageTest { // 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 6b7a18e287..1a7b7b7be0 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 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; @@ -39,4 +42,107 @@ public final class PictureFrameTest { 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 e3a12a8013..4c0f0592de 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 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; @@ -39,4 +43,32 @@ public final class VorbisCommentTest { 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 0000000000..3f60711b19 --- /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 f3e883833a..25d6ceb780 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 final class ChapterFrameTest { 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 0b4a9859c9..f0f8b41b70 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 final class ChapterTocFrameTest { 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 972e855a5b..f08b8f8740 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 final class Id3DecoderTest { @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 final class Id3DecoderTest { @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 final class Id3DecoderTest { @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 final class Id3DecoderTest { 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 final class Id3DecoderTest { @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 final class Id3DecoderTest { 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 48e8fcede3..c42bd61e93 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 final class MlltFrameTest { 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 0000000000..00fdcb6087 --- /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 948cbe2c69..90e28934b0 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 static org.junit.Assert.fail; 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 @@ import org.junit.runner.RunWith; @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); - 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); + state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI); + state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 2); + + 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); - 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(); + 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.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 class AdPlaybackStateTest { @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 class AdPlaybackStateTest { 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 class AdPlaybackStateTest { @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 0000000000..69743bb609 --- /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 1eb49188bf..ae3219f3f2 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 class BaseDataSourceTest { } @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 59a4939a68..432333f09f 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 @@ package com.google.android.exoplayer2.upstream; 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 @@ import org.junit.runner.RunWith; @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 f84b448977..712d17df3b 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 static org.junit.Assert.assertThrows; 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 class DefaultHttpDataSourceTest { 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 0cc71a2881..91ea26b846 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 java.util.List; 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 final class ExoFlagsTest { @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 final class ExoFlagsTest { @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 final class ExoFlagsTest { @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 final class ExoFlagsTest { @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 final class ExoFlagsTest { @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 f8e6061998..d350e99c32 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.times; 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 class ListenerSetTest { 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 class ListenerSetTest { 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 class ListenerSetTest { 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 class ListenerSetTest { 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 class ListenerSetTest { 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 class ListenerSetTest { 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 class ListenerSetTest { 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 class ListenerSetTest { 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 class ListenerSetTest { 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 @@ public class ListenerSetTest { 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 0d41e21496..0888796417 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.android.exoplayer2.video.ColorInfo; 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 2baac87e85..490a68d0ab 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 final class MimeTypesTest { 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 fe081a99db..4d9fc89a03 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 final class NalUnitUtilTest { @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 444e5f7b46..fbf0368c9f 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 final class ParsableByteArrayTest { } 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 final class ParsableByteArrayTest { } 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 final class ParsableByteArrayTest { } 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 final class ParsableByteArrayTest { } 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 final class ParsableByteArrayTest { } 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 final class ParsableByteArrayTest { } 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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { @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 final class ParsableByteArrayTest { 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 0000000000..d7466362be --- /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 d4aaa869f3..7ee41bb895 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 class UtilTest { 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 class UtilTest { 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 class UtilTest { 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 class UtilTest { 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 class UtilTest { .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 class UtilTest { .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 a4cd3bd2a3..81e1a3d543 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 5a33dcf07c..e5a2fac4d9 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 final class ClippedPlaybackTest { .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 final class ClippedPlaybackTest { .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 b59a6e1618..3b65c2c84e 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 @@ public final class ContentDataSourceTest { 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 3d071c204a..a5e53d02d3 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 final class TestContentProvider extends ContentProvider 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 73bb49ed40..99fb0a4112 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 abstract class AbstractConcatenatedTimeline extends Timeline { * @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 abstract class AbstractConcatenatedTimeline extends Timeline { } @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 abstract class AbstractConcatenatedTimeline extends Timeline { 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 198244d9fe..23b5352ed2 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 abstract class BaseRenderer implements Renderer, RendererCapabilities { 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 abstract class BaseRenderer implements Renderer, RendererCapabilities { // 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 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { /** * 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 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { /** * 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 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { 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 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { * * @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 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { * @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 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { } } 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 9ee1846fc1..412a6fdbff 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.MediaClock; 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 @@ import com.google.android.exoplayer2.util.StandaloneMediaClock; 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 d9958fd608..8fd91986c1 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 class DefaultRenderersFactory implements RenderersFactory { 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 @@ public class DefaultRenderersFactory implements RenderersFactory { 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 @@ public class DefaultRenderersFactory implements RenderersFactory { 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 @@ public class DefaultRenderersFactory implements RenderersFactory { 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 @@ public class DefaultRenderersFactory implements RenderersFactory { 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 @@ public class DefaultRenderersFactory implements RenderersFactory { 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 @@ public class DefaultRenderersFactory implements RenderersFactory { 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 @@ public class DefaultRenderersFactory implements RenderersFactory { 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 @@ public class DefaultRenderersFactory implements RenderersFactory { 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 @@ public class DefaultRenderersFactory implements RenderersFactory { * @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 eb04eef9c6..2d78d4409d 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.IntDef; 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.Retention; 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 final class ExoPlaybackException extends Exception implements Bundleable * @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 final class ExoPlaybackException extends Exception implements Bundleable 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 final class ExoPlaybackException extends Exception implements Bundleable 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 final class ExoPlaybackException extends Exception implements Bundleable * @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 @@ public final class ExoPlaybackException extends Exception implements Bundleable /* 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 @@ public final class ExoPlaybackException extends Exception implements Bundleable @Type int type, @Nullable Throwable cause, @Nullable String customMessage, + @ErrorCode int errorCode, @Nullable String rendererName, int rendererIndex, @Nullable Format rendererFormat, @@ -259,6 +217,7 @@ public final class ExoPlaybackException extends Exception implements Bundleable rendererFormat, rendererFormatSupport), cause, + errorCode, type, rendererName, rendererIndex, @@ -269,9 +228,24 @@ public final class ExoPlaybackException extends Exception implements Bundleable 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 @@ public final class ExoPlaybackException extends Exception implements Bundleable @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 @@ public final class ExoPlaybackException extends Exception implements Bundleable */ public IOException getSourceException() { Assertions.checkState(type == TYPE_SOURCE); - return (IOException) Assertions.checkNotNull(cause); + return (IOException) Assertions.checkNotNull(getCause()); } /** @@ -310,7 +283,7 @@ public final class ExoPlaybackException extends Exception implements Bundleable */ public Exception getRendererException() { Assertions.checkState(type == TYPE_RENDERER); - return (Exception) Assertions.checkNotNull(cause); + return (Exception) Assertions.checkNotNull(getCause()); } /** @@ -320,7 +293,24 @@ public final class ExoPlaybackException extends Exception implements Bundleable */ 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 final class ExoPlaybackException extends Exception implements Bundleable /* package */ ExoPlaybackException copyWithMediaPeriodId(@Nullable MediaPeriodId mediaPeriodId) { return new ExoPlaybackException( Util.castNonNull(getMessage()), - cause, + getCause(), + errorCode, type, rendererName, rendererIndex, @@ -382,33 +373,16 @@ public final class ExoPlaybackException extends Exception implements Bundleable } // 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 @@ public final class ExoPlaybackException extends Exception implements Bundleable */ @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 c98e78e159..cd4d855f1e 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 @@ import java.util.List; * 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 @@ import java.util.List; * {@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 interface ExoPlayer extends Player { analyticsCollector, useLazyPreparation, seekParameters, + C.DEFAULT_SEEK_BACK_INCREMENT_MS, + C.DEFAULT_SEEK_FORWARD_INCREMENT_MS, livePlaybackSpeedControl, releaseTimeoutMs, pauseAtEndOfMediaItems, @@ -843,6 +845,13 @@ public interface ExoPlayer extends Player { } } + /** + * 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 8ee7cf8687..85723c4dee 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 @@ import java.util.concurrent.CopyOnWriteArraySet; @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 @@ import java.util.concurrent.CopyOnWriteArraySet; 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 @@ import java.util.concurrent.CopyOnWriteArraySet; * 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 @@ import java.util.concurrent.CopyOnWriteArraySet; @Nullable AnalyticsCollector analyticsCollector, boolean useLazyPreparation, SeekParameters seekParameters, + long seekBackIncrementMs, + long seekForwardIncrementMs, LivePlaybackSpeedControl livePlaybackSpeedControl, long releaseTimeoutMs, boolean pauseAtEndOfMediaItems, @@ -169,6 +176,8 @@ import java.util.concurrent.CopyOnWriteArraySet; 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 @@ import java.util.concurrent.CopyOnWriteArraySet; 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 @@ import java.util.concurrent.CopyOnWriteArraySet; 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 @@ import java.util.concurrent.CopyOnWriteArraySet; 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 @@ import java.util.concurrent.CopyOnWriteArraySet; // 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 @@ import java.util.concurrent.CopyOnWriteArraySet; 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 @@ import java.util.concurrent.CopyOnWriteArraySet; return new TrackSelectionArray(playbackInfo.trackSelectorResult.selections); } + @Deprecated @Override public List getCurrentStaticMetadata() { return playbackInfo.staticMetadata; @@ -998,6 +1026,23 @@ import java.util.concurrent.CopyOnWriteArraySet; 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 @@ import java.util.concurrent.CopyOnWriteArraySet; .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 @@ import java.util.concurrent.CopyOnWriteArraySet; 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 @@ import java.util.concurrent.CopyOnWriteArraySet; 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 116cb7d19f..a497f20b09 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 android.util.Pair; 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.ExoTrackSelection; 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 @@ import java.util.concurrent.atomic.AtomicBoolean; default: return false; } - maybeNotifyPlaybackInfoChanged(); } catch (ExoPlaybackException e) { if (e.type == ExoPlaybackException.TYPE_RENDERER) { @Nullable MediaPeriodHolder readingPeriod = queue.getReadingPeriod(); @@ -571,30 +574,60 @@ import java.util.concurrent.atomic.AtomicBoolean; 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 @@ import java.util.concurrent.atomic.AtomicBoolean; 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 @@ import java.util.concurrent.atomic.AtomicBoolean; // 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 @@ import java.util.concurrent.atomic.AtomicBoolean; 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 @@ import java.util.concurrent.atomic.AtomicBoolean; 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 @@ import java.util.concurrent.atomic.AtomicBoolean; } 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 @@ import java.util.concurrent.atomic.AtomicBoolean; 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 @@ import java.util.concurrent.atomic.AtomicBoolean; // 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 @@ import java.util.concurrent.atomic.AtomicBoolean; 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 c35f6fa95e..dbc86bdb3d 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.Retention; 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 d8569a544d..2e0d193ee3 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; /** 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } /** 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 b14af5e1de..aa9455fcbe 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 @@ package com.google.android.exoplayer2; 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 @@ import com.google.android.exoplayer2.util.Util; * 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 @@ import com.google.android.exoplayer2.util.Util; 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 @@ import com.google.android.exoplayer2.util.Util; requestedContentPositionUs, endPositionUs, durationUs, + isFollowedByTransitionToSameStream, isLastInTimelinePeriod, isLastInTimelineWindow, isFinal); @@ -111,6 +126,7 @@ import com.google.android.exoplayer2.util.Util; requestedContentPositionUs, endPositionUs, durationUs, + isFollowedByTransitionToSameStream, isLastInTimelinePeriod, isLastInTimelineWindow, isFinal); @@ -129,6 +145,7 @@ import com.google.android.exoplayer2.util.Util; && 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 @@ import com.google.android.exoplayer2.util.Util; 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 d72eaa15db..18b258d779 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 @@ import com.google.common.collect.ImmutableList; 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 @@ import com.google.common.collect.ImmutableList; 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 @@ import com.google.common.collect.ImmutableList; } 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 @@ import com.google.common.collect.ImmutableList; 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 @@ import com.google.common.collect.ImmutableList; 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 @@ import com.google.common.collect.ImmutableList; contentPositionUs, /* endPositionUs= */ C.TIME_UNSET, durationUs, + isFollowedByTransitionToSameStream, /* isLastInTimelinePeriod= */ false, /* isLastInTimelineWindow= */ false, /* isFinal= */ false); @@ -793,6 +814,8 @@ import com.google.common.collect.ImmutableList; 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 @@ import com.google.common.collect.ImmutableList; requestedContentPositionUs, endPositionUs, durationUs, + isFollowedByTransitionToSameStream, isLastInPeriod, isLastInWindow, isLastInTimeline); @@ -837,4 +861,14 @@ import com.google.common.collect.ImmutableList; && 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 f3329b8ea7..39dd111078 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 abstract class NoSampleRenderer implements Renderer, RendererCapabilities } @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 abstract class NoSampleRenderer implements Renderer, RendererCapabilities // 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 abstract class NoSampleRenderer implements Renderer, RendererCapabilities /** * 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 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities /** * 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 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities } /** - * 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 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities /** * 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 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities /** * 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 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities 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 9ccc2a5a40..e525b5130d 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.android.exoplayer2.trackselection.TrackSelectorResult; 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 57c70cd5ca..6ff7100ad1 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 final class PlayerMessage { * 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 final class PlayerMessage { /** * 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 f84fef5004..3e1d913829 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 @@ public interface Renderer extends PlayerMessage.Target { /** * 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 @@ public interface Renderer extends PlayerMessage.Target { /** * 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 @@ public interface Renderer extends PlayerMessage.Target { /** * 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 @@ public interface Renderer extends PlayerMessage.Target { /** * 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 @@ public interface Renderer extends PlayerMessage.Target { /** * 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 @@ public interface Renderer extends PlayerMessage.Target { /** * 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 @@ public interface Renderer extends PlayerMessage.Target { /** * 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 dc7a8f8642..37176cb752 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 bac2e82c60..04ded28f2f 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_SKIP_SILENCE_ENABLE 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.Surface; 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 class SimpleExoPlayer extends BasePlayer @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 class SimpleExoPlayer extends BasePlayer *

      • {@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 class SimpleExoPlayer extends BasePlayer 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 class SimpleExoPlayer extends BasePlayer 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 @@ public class SimpleExoPlayer extends BasePlayer analyticsCollector, builder.useLazyPreparation, builder.seekParameters, + builder.seekBackIncrementMs, + builder.seekForwardIncrementMs, builder.livePlaybackSpeedControl, builder.releaseTimeoutMs, builder.pauseAtEndOfMediaItems, @@ -1263,17 +1303,17 @@ public class SimpleExoPlayer extends BasePlayer @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 class SimpleExoPlayer extends BasePlayer 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 class SimpleExoPlayer extends BasePlayer return player.getCurrentTrackSelections(); } + @Deprecated @Override public List getCurrentStaticMetadata() { verifyApplicationThread(); @@ -1676,6 +1735,16 @@ public class SimpleExoPlayer extends BasePlayer 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 @@ public class SimpleExoPlayer extends BasePlayer .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 @@ public class SimpleExoPlayer extends BasePlayer } 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 @@ public class SimpleExoPlayer extends BasePlayer } } 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 @@ public class SimpleExoPlayer extends BasePlayer @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 5d1c0a9c2f..00d7547202 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.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.PlaybackSuppressionReason; @@ -49,6 +51,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectionArray; 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 class AnalyticsCollector 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 class AnalyticsCollector 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 class AnalyticsCollector } } - // 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 class AnalyticsCollector 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 class AnalyticsCollector listener -> listener.onTracksChanged(eventTime, trackGroups, trackSelections)); } + @Deprecated @Override public final void onStaticMetadataChanged(List metadataList) { EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); @@ -631,6 +625,15 @@ public class AnalyticsCollector }); } + @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 class AnalyticsCollector } @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 class AnalyticsCollector } @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 class AnalyticsCollector 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 class AnalyticsCollector 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 class AnalyticsCollector 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 class AnalyticsCollector listener -> listener.onDrmSessionReleased(eventTime)); } + // Internal methods. + /** * Sends an event to registered listeners. * @@ -892,8 +951,6 @@ public class AnalyticsCollector 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 6550c5ac05..a8c9ed38a0 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 android.view.Surface; 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.LoadEventInfo; 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 interface AnalyticsListener { 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 interface AnalyticsListener { * {@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 interface AnalyticsListener { 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 @@ public interface AnalyticsListener { 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 @@ public interface AnalyticsListener { @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 @@ public interface AnalyticsListener { 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 @@ public interface AnalyticsListener { * 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 @@ public interface AnalyticsListener { * 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 @@ public interface AnalyticsListener { * 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 @@ public interface AnalyticsListener { * 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 2ca886a5e6..fd349ea60c 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.os.SystemClock; 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 final class PlaybackStatsListener // 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 final class PlaybackStatsListener @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 final class PlaybackStatsListener 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 643f91078e..a12f63deeb 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 final class AudioCapabilities { && 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 final class AudioCapabilities { 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 final class AudioCapabilities { @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 @@ public final class AudioCapabilities { } @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 c9c78a7422..caed07b6ad 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 @@ import com.google.android.exoplayer2.util.Util; */ public final class AudioCapabilitiesReceiver { - /** - * Listener notified when audio capabilities change. - */ + /** Listener notified when audio capabilities change. */ public interface Listener { /** @@ -45,7 +43,6 @@ public final class AudioCapabilitiesReceiver { * @param audioCapabilities The current audio capabilities for the device. */ void onAudioCapabilitiesChanged(AudioCapabilities audioCapabilities); - } private final Context context; @@ -77,8 +74,8 @@ public final class AudioCapabilitiesReceiver { /** * 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 final class AudioCapabilitiesReceiver { 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 f75b2cd317..e0d856e47d 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 @@ public interface AudioProcessor { public UnhandledAudioFormatException(AudioFormat inputAudioFormat) { super("Unhandled format: " + inputAudioFormat); } - } /** An empty, direct {@link ByteBuffer}. */ @@ -109,16 +108,16 @@ public interface AudioProcessor { * 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 adf475ef35..8f38dacf5d 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 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.PlaybackParameters; import com.google.android.exoplayer2.Player; import java.lang.annotation.Documented; @@ -57,9 +58,7 @@ import java.nio.ByteBuffer; */ public interface AudioSink { - /** - * Listener for audio sink events. - */ + /** Listener for audio sink events. */ interface Listener { /** @@ -124,7 +123,7 @@ public interface AudioSink { * 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 @@ public interface AudioSink { 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 @@ public interface AudioSink { /** * 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 interface AudioSink { this.errorCode = errorCode; this.format = format; } - } /** Thrown when the sink encounters an unexpected timestamp discontinuity. */ @@ -327,9 +323,7 @@ public interface AudioSink { 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 @@ public interface AudioSink { */ 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 @@ public 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. * @@ -432,9 +424,7 @@ public interface AudioSink { */ 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 8891a6d8d1..6c26d87fcf 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 @@ import java.lang.reflect.Method; * @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 c064c7e459..74c78b1af3 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 @@ import java.nio.ByteBuffer; 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 4367883df9..286efe08e1 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.ExoPlaybackException; 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 abstract class 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 abstract class DecoderAudioRenderer< 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 abstract class DecoderAudioRenderer< 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 abstract class DecoderAudioRenderer< 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 @@ public abstract class DecoderAudioRenderer< 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 @@ public abstract class DecoderAudioRenderer< } 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 @@ public abstract class DecoderAudioRenderer< 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 47bfba9efe..376776575b 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 final class DefaultAudioSink implements AudioSink { private InvalidAudioTrackTimestampException(String message) { super(message); } - } /** @@ -221,7 +220,8 @@ public final class DefaultAudioSink implements AudioSink { @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 final class DefaultAudioSink implements AudioSink { * 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 final class DefaultAudioSink implements AudioSink { /** * 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 @@ public final class DefaultAudioSink implements AudioSink { 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 final class DefaultAudioSink implements AudioSink { // 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 @@ public final class DefaultAudioSink implements AudioSink { 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 2fc8667bc5..0e3aa17212 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.ExoPlaybackException; 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 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media 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 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media 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 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media 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 a4d2a1b67a..14ba4788e3 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 @@ import java.nio.ByteBuffer; 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 5ddedd7bd7..58cd145e35 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 @@ import java.util.Arrays; /** * 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 @@ import java.util.Arrays; } } } - } 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 bbfd77469d..b7d14667be 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 final class SonicAudioProcessor implements AudioProcessor { 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 ed51726530..bd3017bf53 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 @@ import java.nio.ByteBuffer; 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 c94eb2c38a..68852182ae 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 698e329be5..779513d412 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 @@ import static java.lang.Math.max; */ 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 073f6ecca7..bce21cca9c 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 abstract class OutputBuffer extends Buffer { 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 abstract class OutputBuffer extends Buffer { */ 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 da69924e03..896fb06568 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 abstract class SimpleDecoder< /** * 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 abstract class SimpleDecoder< 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 @@ public abstract class SimpleDecoder< /** * 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 @@ public abstract class SimpleDecoder< 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 12d3c8ca26..81561701e2 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 class SimpleOutputBuffer extends OutputBuffer { 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 1c64570f9e..0aace3f95f 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.JSONArray; 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 @@ import org.json.JSONObject; 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 f144cc1ac2..eddaba3d93 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 @@ package com.google.android.exoplayer2.drm; /** 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 class DecryptionException extends Exception { 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 f4932590ab..ca7a657a0f 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } } - 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; + 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; Util.castNonNull(requestHandler) .post(MSG_KEYS, Assertions.checkNotNull(currentKeyRequest), allowRetry); } catch (Exception e) { - onKeysError(e); + onKeysError(e, /* thrownByExoMediaDrm= */ true); } } @@ -469,7 +475,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; currentKeyRequest = null; if (response instanceof Exception) { - onKeysError((Exception) response); + onKeysError((Exception) response, /* thrownByExoMediaDrm= */ false); return; } @@ -491,7 +497,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; dispatchEvent(DrmSessionEventListener.EventDispatcher::drmKeysLoaded); } } catch (Exception e) { - onKeysError(e); + onKeysError(e, /* thrownByExoMediaDrm= */ true); } } @@ -502,16 +508,21 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } } - 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } @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 5680627b32..774e91eee8 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.Nullable; 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 @@ public class DefaultDrmSessionManager implements DrmSessionManager { 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 class DefaultDrmSessionManager implements DrmSessionManager { } @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 e72d552a68..b993345613 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 @@ package com.google.android.exoplayer2.drm; 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 @@ public interface DrmSession { /** Wraps the throwable which is the cause of the error state. */ class DrmSessionException extends IOException { - public DrmSessionException(Throwable cause) { - super(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 interface DrmSession { * 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 interface DrmSession { 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 4b3ee553d8..b056f6ab0d 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 @@ package com.google.android.exoplayer2.drm; 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 interface DrmSessionManager { } 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 0000000000..cb92010110 --- /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 6a5dffc6b8..b20fc916c4 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 @@ import java.util.UUID; /** * 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 a54975392b..48255714bd 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 final class FrameworkMediaDrm implements ExoMediaDrm { } @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 6a20cf7bda..d5288a1b35 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 final class HttpMediaDrmCallback implements MediaDrmCallback { } } - /** - * 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 final class HttpMediaDrmCallback implements MediaDrmCallback { } 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 d141b6c4c1..a95291413f 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 final class LocalMediaDrmCallback implements MediaDrmCallback { 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 b218d0cadb..bfa9d191c4 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 final class 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 final class OfflineLicenseHelper { 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 @@ public final class OfflineLicenseHelper { 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 cd728df1b2..e52c770388 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 final class UnsupportedDrmException extends Exception { 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 a5998488f2..2af6a5cd1b 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 @@ public final class 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 @@ public final class WidevineUtil { } 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 6d77cdac8d..dffdef4280 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 @@ import java.nio.ByteBuffer; 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 @@ import java.nio.ByteBuffer; @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 @@ import java.nio.ByteBuffer; 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; + TraceUtil.endSection(); + bufferEnqueuer.start(); + TraceUtil.beginSection("startCodec"); + codec.start(); + TraceUtil.endSection(); + state = STATE_INITIALIZED; } - private void start() { - bufferEnqueuer.start(); - codec.start(); - state = STATE_STARTED; + @Override + public boolean needsReconfiguration() { + return false; } @Override @@ -248,10 +247,8 @@ import java.nio.ByteBuffer; @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 368444f81d..0b8fffd6e9 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 @@ public interface MediaCodecAdapter { * @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 99396af2f4..6d4c11603a 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 final class MediaCodecInfo { * @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 final class MediaCodecInfo { 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 final class MediaCodecInfo { } 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 @@ public final class MediaCodecInfo { // 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 da97a60c0a..9d689faa03 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.C; 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 abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { * 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { }) 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 abstract class MediaCodecRenderer extends BaseRenderer { 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 abstract class MediaCodecRenderer extends BaseRenderer { 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 abstract class MediaCodecRenderer extends BaseRenderer { * @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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { releaseCodec(); } throw createRendererException( - createDecoderException(e, getCodecInfo()), inputFormat, isRecoverable); + createDecoderException(e, getCodecInfo()), + inputFormat, + isRecoverable, + PlaybackException.ERROR_CODE_DECODING_FAILED); } throw e; } @@ -1051,6 +1034,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { DecoderInitializationException exception = new DecoderInitializationException( inputFormat, e, mediaCryptoRequiresSecureDecoder, codecInfo); + onCodecError(exception); if (preferredDecoderInitializationException == null) { preferredDecoderInitializationException = exception; } else { @@ -1154,6 +1138,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { resetInputBuffer(); } } catch (CryptoException e) { - throw createRendererException(e, inputFormat); + throw createRendererException( + e, inputFormat, C.getErrorCodeForMediaDrmErrorCode(e.getErrorCode())); } return false; } @@ -1384,7 +1370,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { /** * 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } if (codec == null) { - if (!legacyKeepAvailableCodecInfosWithoutCodec()) { - availableCodecInfos = null; - } + availableCodecInfos = null; maybeInitCodecOrBypass(); return null; } @@ -1550,14 +1539,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { /** * 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { // 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { /** * 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { * @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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { * @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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { /** * 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 @@ public abstract class MediaCodecRenderer extends BaseRenderer { * 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 7eac7a21c2..ad16170b0b 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 final class MediaCodecUtil { private DecoderQueryException(Throwable cause) { super("Failed to query underlying media codecs", cause); } - } private static final String TAG = "MediaCodecUtil"; @@ -175,8 +174,12 @@ public final class MediaCodecUtil { 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 @@ public final class MediaCodecUtil { */ @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 @@ public final class MediaCodecUtil { } // 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 @@ public final class MediaCodecUtil { private interface MediaCodecListCompat { - /** - * The number of codecs in the list. - */ + /** The number of codecs in the list. */ int getCodecCount(); /** @@ -932,9 +932,7 @@ public final class MediaCodecUtil { */ 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 @@ public final class MediaCodecUtil { mediaCodecInfos = new MediaCodecList(codecKind).getCodecInfos(); } } - } private static final class MediaCodecListCompatV16 implements MediaCodecListCompat { @@ -1027,7 +1024,6 @@ public final class MediaCodecUtil { 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 67fb24f1dd..90bf99fa06 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 @@ public class SynchronousMediaCodecAdapter implements MediaCodecAdapter { } } + @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 182e4e5303..afb32ee211 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 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { 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 f1ceaa3bb4..a849851aa0 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 @@ import com.google.android.exoplayer2.util.Util; /** 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 @@ public final class PrivateCommand extends SpliceCommand { 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 final class PrivateCommand extends SpliceCommand { 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 8cb4dcec2b..40da002c04 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 abstract class SpliceCommand implements Metadata.Entry { 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 fbcf9da6f3..f26d446b80 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 @@ public final class SpliceInfoDecoder extends SimpleMetadataDecoder { 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 @@ public final class SpliceInfoDecoder extends SimpleMetadataDecoder { } 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 8c8c6a1ffb..e5df2b963b 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 @@ import java.util.List; /** 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 @@ public final class SpliceInsertCommand extends SpliceCommand { 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 @@ public final class SpliceInsertCommand extends SpliceCommand { 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 @@ public final class SpliceInsertCommand extends SpliceCommand { 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 final class SpliceInsertCommand extends SpliceCommand { public static ComponentSplice createFromParcel(Parcel in) { return new ComponentSplice(in.readInt(), in.readLong(), in.readLong()); } - } // Parcelable implementation. @@ -237,16 +243,14 @@ public final class SpliceInsertCommand extends SpliceCommand { 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 aed0a0e2bc..196f297970 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 final class SpliceNullCommand extends SpliceCommand { 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 e252ae7354..6e62177fc7 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 @@ import java.util.List; /** 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 final class SpliceScheduleCommand extends SpliceCommand { */ 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 final class SpliceScheduleCommand extends SpliceCommand { * 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 @@ public final class SpliceScheduleCommand extends SpliceCommand { 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 @@ public final class SpliceScheduleCommand extends SpliceCommand { 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 @@ public final class SpliceScheduleCommand extends SpliceCommand { 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 final class SpliceScheduleCommand extends SpliceCommand { 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 5115b7a722..aec2a91731 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 @@ import com.google.android.exoplayer2.util.TimestampAdjuster; /** 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 @@ public final class TimeSignalCommand extends SpliceCommand { 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 final class TimeSignalCommand extends SpliceCommand { 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 2a62b0602c..3388424e6e 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 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex { } /** 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 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex { 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 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex { */ 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 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex { 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 365a4439a1..bed0bb26a3 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 @@ public class DefaultDownloaderFactory implements DownloaderFactory { } } - // LINT.IfChange private static SparseArray> createDownloaderConstructors() { SparseArray> array = new SparseArray<>(); try { @@ -150,5 +149,4 @@ public class DefaultDownloaderFactory implements DownloaderFactory { 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 983727c14d..2f7d7eba89 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 final class DownloadException extends IOException { 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 27ff0a7956..38448f61b6 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 @@ public final class DownloadHelper { "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 final class 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 a989e2575f..95705a9caa 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 final class 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 final class 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 @@ public final class DownloadManager { 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 f98ca3eac3..435c5aa00c 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 35a3e788f5..5be5ea785d 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 final class ProgressiveDownloader implements Downloader { 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 final class ProgressiveDownloader implements Downloader { .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 74df93d82f..7156f50a22 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 abstract class SegmentDownloader> impleme 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 2d56762175..743659773a 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 6a58605480..1a9ad2dae9 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 final class ClippingMediaSource extends CompositeMediaSource { /** 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 final class ClippingMediaSource extends CompositeMediaSource { 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 @@ public final class ClippingMediaSource extends CompositeMediaSource { 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 1507068664..8492245442 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 48305bc916..bb9098be4d 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 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { 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 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { } 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 fb732ad10d..009c6466d1 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 abstract class ForwardingTimeline extends Timeline { } @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 285b9f3fef..cab324fc13 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 @@ import java.util.Map; } @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 @@ import java.util.Map; 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 d10651a575..99e62728ac 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 final class LoopingMediaSource extends CompositeMediaSource { 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 final class LoopingMediaSource extends CompositeMediaSource { 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 @@ public final class LoopingMediaSource extends CompositeMediaSource { protected Object getChildUidByChildIndex(int childIndex) { return childIndex; } - } private static final class InfinitelyLoopingTimeline extends ForwardingTimeline { @@ -225,23 +214,23 @@ public final class LoopingMediaSource extends CompositeMediaSource { } @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 2151119abf..7c60a379c7 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 final class MaskingMediaPeriod implements MediaPeriod, MediaPeriod.Callba } @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 e7c27ba95e..c1744ed57a 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 final class MaskingMediaSource extends CompositeMediaSource { } } - /** - * @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 683912448d..5f5eb38db7 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 @@ package com.google.android.exoplayer2.source; 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 final class MediaLoadData { * @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 4b5229ba00..2117883f4d 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 @@ public interface MediaSource { 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 c5859fecbc..115bff2a99 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 android.os.Handler; 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 interface MediaSourceEventListener { } /** 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 interface MediaSourceEventListener { /** 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 interface MediaSourceEventListener { } /** 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 interface MediaSourceEventListener { /** 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 interface MediaSourceEventListener { } /** 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 interface MediaSourceEventListener { /** 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 interface MediaSourceEventListener { * 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 interface MediaSourceEventListener { */ 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 3a9bfe4f91..f4d44b9540 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 @@ import java.util.Map; */ 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 final class MergingMediaSource extends CompositeMediaSource { @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 final class MergingMediaSource extends CompositeMediaSource { 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 791dd72479..2ffe134fa4 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.net.Uri; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; Loader.ReleaseCallback, UpstreamFormatChangedListener { - /** - * Listener for information about the period. - */ + /** Listener for information about the period. */ interface Listener { /** @@ -129,7 +128,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; if (largestQueuedTimestampUs == Long.MAX_VALUE) { largestQueuedTimestampUs = getLargestQueuedTimestampUs(); } - return largestQueuedTimestampUs == Long.MIN_VALUE ? lastSeekPositionUs + return largestQueuedTimestampUs == Long.MIN_VALUE + ? lastSeekPositionUs : largestQueuedTimestampUs; } @@ -552,8 +550,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @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 4c9ce82495..9243ed5975 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 @@ public final class ProgressiveMediaSource extends BaseMediaSource 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 def7cb16bb..7b5c6a35f7 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 class SampleQueue implements TrackOutput { @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 e500d0520a..91f0e9b820 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 @@ import com.google.android.exoplayer2.C; /** 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 @@ public interface SequenceableLoader { * to be called when it can continue to load data. Called on the playback thread. */ void onContinueLoadingRequested(T source); - } /** @@ -42,19 +39,17 @@ public interface SequenceableLoader { */ 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 5af9dbd20a..e8f804fbe0 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 @@ import java.util.Random; */ 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 @@ public interface ShuffleOrder { } 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 interface ShuffleOrder { } } - /** - * 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 35e5e6f8c0..725100b583 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 final class SilenceMediaSource extends BaseMediaSource { @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 26438dbb77..314946f90a 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 3d557cf17d..45f33c39c9 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 @@ public final class SingleSampleMediaSource extends BaseMediaSource { // 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 324f89794a..ec94e40777 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 906139cf76..f937b0a07b 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 @@ public interface AdsLoader { /** * 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 f9a3daca86..182ead64d1 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 final class AdsMediaSource extends CompositeMediaSource { 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 @@ public final class AdsMediaSource extends CompositeMediaSource { @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 0000000000..69588f504c --- /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 0000000000..65567d005b --- /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 c1a655e522..a114bd92d9 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 final class SinglePeriodAdTimeline extends ForwardingTimeline { 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 8693bb8912..330bb494da 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 abstract class BaseMediaChunk extends MediaChunk { 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 abstract class BaseMediaChunk extends MediaChunk { 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 274be54889..a46fc10606 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 961d1f8db6..f7b2524e07 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 final class BaseMediaChunkOutput implements TrackOutputProvider { 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 final class BaseMediaChunkOutput implements TrackOutputProvider { 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 ff19ee1d26..322ee748fd 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 final class BundledChunkExtractor implements ExtractorOutput, ChunkExtrac // 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 1c729b3f35..c2d00123b7 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 @@ package com.google.android.exoplayer2.source.chunk; 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 abstract class Chunk implements Loadable { 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 da0a71e82d..8d47ac7ad9 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 40c1b7f357..b6cd400f22 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 class ChunkSampleStream 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 class ChunkSampleStream } 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 class ChunkSampleStream 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 @@ public class ChunkSampleStream 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 @@ public class ChunkSampleStream } } } - } 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 81ce2d63de..b2a46a0cd4 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 @@ public interface ChunkSource { * * @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 cec6c0ee02..aa705bc101 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 @@ package com.google.android.exoplayer2.source.chunk; 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 944b25395a..b9717a3d46 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 final class InitializationChunk extends Chunk { 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 690b9db4d8..7e4913db15 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 abstract class MediaChunk extends Chunk { 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 abstract class MediaChunk extends Chunk { 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 fadf7ad6f7..47467bc2ea 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 final class MediaParserChunkExtractor implements ChunkExtractor { } @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 4c84a91be2..1ded32b70c 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 final class SingleSampleMediaChunk extends BaseMediaChunk { 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 f3bed012ec..648f1c7275 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 @@ public final class OutputConsumerAdapterV30 implements MediaParser.OutputConsume @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 fb5e1f198a..3325bdc723 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 abstract class SimpleSubtitleDecoder } @Override - public void setPositionUs(long timeUs) { + public void setPositionUs(long positionUs) { // Do nothing } @@ -89,5 +89,4 @@ public abstract class SimpleSubtitleDecoder */ 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 6807661c84..ab2736e680 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 @@ package com.google.android.exoplayer2.text; 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 861faa73f9..6581939d07 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 7571b0ffef..e02ac36e5c 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 7de577f18c..05d10c4786 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 @@ import com.google.android.exoplayer2.decoder.DecoderException; /** 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 9866517a58..1e80a62e11 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 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; 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 1dfa9ffb45..7d9c8d9c32 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 abstract class SubtitleOutputBuffer extends OutputBuffer implements Subti 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 c721fe8da0..5a27d5bb3a 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 97890d7ee5..b0e3f3f15e 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 @@ public final class Cea608Decoder extends CeaDecoder { 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 @@ public final class Cea608Decoder extends CeaDecoder { // 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 final class Cea608Decoder extends CeaDecoder { 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 e91edcd307..d09be81f37 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 final class Cea708Decoder extends CeaDecoder { packetData = new byte[2 * packetSize - 1]; currentIndex = 0; } - } // TODO: There is a lot of overlap between Cea708Decoder.CueInfoBuilder and @@ -872,45 +871,64 @@ public final class Cea708Decoder extends CeaDecoder { 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 final class Cea708Decoder extends CeaDecoder { 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 final class Cea708Decoder extends CeaDecoder { // 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 final class Cea708Decoder extends CeaDecoder { 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 final class Cea708Decoder extends CeaDecoder { 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 final class Cea708Decoder extends CeaDecoder { 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 final class Cea708Decoder extends CeaDecoder { 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 final class Cea708Decoder extends CeaDecoder { 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 final class Cea708Decoder extends CeaDecoder { // 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 81ef58a712..4db023cc9c 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 com.google.android.exoplayer2.util.Util; 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 @@ import java.util.PriorityQueue; 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 @@ import java.util.PriorityQueue; // 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 738f251e27..bc02caf5c0 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 com.google.android.exoplayer2.util.Assertions; 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 @@ import java.util.List; 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 22ce893fce..0e98a2e7eb 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 @@ public final class DvbDecoder extends SimpleSubtitleDecoder { } 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 5cdbfdf72e..1d5ec8454c 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.Collections; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } // 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; // Private inner classes. - /** - * The subtitle service definition. - */ + /** The subtitle service definition. */ private static final class SubtitleService { public final int subtitlePageId; @@ -890,13 +936,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 75728359c7..de9cf45369 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.Cue; 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 @@ import java.util.List; 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 3ae6bd133d..cf1ae43a36 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 @@ import java.util.regex.Pattern; ? 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 4093f7974d..79da60c34e 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 com.google.android.exoplayer2.util.Util; 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 01ed1711a9..631a638408 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 com.google.android.exoplayer2.util.Util; 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 @@ import java.util.List; 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 1d84b7a6b3..6a57e14970 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 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder { } 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 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder { || 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 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder { @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 7e39d1e9f8..0677ef1e27 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.TreeMap; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 36c862568f..593bfd7761 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 @@ package com.google.android.exoplayer2.text.ttml; 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 @@ import com.google.android.exoplayer2.text.Cue; 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 e578a04072..8d2724622e 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.ArrayDeque; 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 @@ import java.util.Map; @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 @@ import java.util.Map; 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 @@ import java.util.Map; } 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 d1c7291652..82ce86df2a 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.Documented; 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 @@ import java.lang.annotation.RetentionPolicy; * @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 @@ import java.lang.annotation.RetentionPolicy; 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 6a52338a94..68c11a9a25 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.Collections; 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 ea08c375ef..4b8f539f42 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 final class Tx3gDecoder extends SimpleSubtitleDecoder { && (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 @@ public final class Tx3gDecoder extends SimpleSubtitleDecoder { } // 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 @@ public final class Tx3gDecoder extends SimpleSubtitleDecoder { 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 @@ public final class Tx3gDecoder extends SimpleSubtitleDecoder { 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 @@ public final class Tx3gDecoder extends SimpleSubtitleDecoder { } } - 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 adb1190ce4..100e080056 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 com.google.android.exoplayer2.util.Assertions; 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 @@ import java.util.List; 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 c87c88133c..00c8ecdc48 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 com.google.android.exoplayer2.util.Assertions; 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 0bd1312942..6fd236e98f 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 androidx.annotation.Nullable; 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 @@ import java.util.regex.Pattern; * 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; // --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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; } 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; 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 b8f9e9b343..587f7d5ab5 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 final class WebvttCssStyle { } public void setTargetId(String targetId) { - this.targetId = targetId; + this.targetId = targetId; } public void setTargetTagName(String targetTag) { @@ -134,24 +134,27 @@ public final class WebvttCssStyle { /** * 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 final class WebvttCssStyle { * @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 final class WebvttCssStyle { this.underline = underline ? ON : OFF; return this; } + public WebvttCssStyle setBold(boolean bold) { this.bold = bold ? ON : OFF; return this; @@ -259,12 +263,13 @@ public final class WebvttCssStyle { 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 @@ public final class WebvttCssStyle { } 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 a040a3acf3..63cfc8b8dd 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 final class WebvttCueParser { boolean isClosingTag = markup.charAt(ltPos + 1) == CHAR_SLASH; pos = findEndOfTag(markup, ltPos + 1); boolean isVoidTag = markup.charAt(pos - 2) == CHAR_SLASH; - String fullTagExpression = markup.substring(ltPos + (isClosingTag ? 2 : 1), - isVoidTag ? pos - 2 : pos - 1); + String fullTagExpression = + markup.substring(ltPos + (isClosingTag ? 2 : 1), isVoidTag ? pos - 2 : pos - 1); if (fullTagExpression.trim().isEmpty()) { continue; } @@ -535,14 +535,12 @@ public final class WebvttCueParser { int start = startTag.position; int end = text.length(); - switch(startTag.name) { + switch (startTag.name) { case TAG_BOLD: - text.setSpan(new StyleSpan(STYLE_BOLD), start, end, - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new StyleSpan(STYLE_BOLD), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); break; case TAG_ITALIC: - text.setSpan(new StyleSpan(STYLE_ITALIC), start, end, - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new StyleSpan(STYLE_ITALIC), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); break; case TAG_RUBY: applyRubySpans(text, cueId, startTag, nestedElements, styles); @@ -658,8 +656,8 @@ public final class WebvttCueParser { } } - private static void applyStyleToText(SpannableStringBuilder spannedText, WebvttCssStyle style, - int start, int end) { + private static void applyStyleToText( + SpannableStringBuilder spannedText, WebvttCssStyle style, int start, int end) { if (style == null) { return; } @@ -924,7 +922,6 @@ public final class WebvttCueParser { public int compareTo(StyleMatch another) { return Integer.compare(this.score, another.score); } - } private static final class StartTag { @@ -968,7 +965,6 @@ public final class WebvttCueParser { /* voice= */ "", /* classes= */ Collections.emptySet()); } - } /** Information about a complete element (i.e. start tag and end position). */ diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoder.java index 383c90af36..0d04a3f4be 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoder.java @@ -44,12 +44,12 @@ public final class WebvttDecoder extends SimpleSubtitleDecoder { private static final String STYLE_START = "STYLE"; private final ParsableByteArray parsableWebvttData; - private final CssParser cssParser; + private final WebvttCssParser cssParser; public WebvttDecoder() { super("WebvttDecoder"); parsableWebvttData = new ParsableByteArray(); - cssParser = new CssParser(); + cssParser = new WebvttCssParser(); } @Override @@ -117,5 +117,4 @@ public final class WebvttDecoder extends SimpleSubtitleDecoder { private static void skipComment(ParsableByteArray parsableWebvttData) { while (!TextUtils.isEmpty(parsableWebvttData.readLine())) {} } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttParserUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttParserUtil.java index 07b1fb7f9c..52f0cdb8d1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttParserUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttParserUtil.java @@ -40,7 +40,8 @@ public final class WebvttParserUtil { int startPosition = input.getPosition(); if (!isWebvttHeaderLine(input)) { input.setPosition(startPosition); - throw new ParserException("Expected WEBVTT. Got " + input.readLine()); + throw ParserException.createForMalformedContainer( + "Expected WEBVTT. Got " + input.readLine(), /* cause= */ null); } } @@ -113,5 +114,4 @@ public final class WebvttParserUtil { } return null; } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttSubtitle.java b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttSubtitle.java index 4a8f5a5471..301f4ea19a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttSubtitle.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttSubtitle.java @@ -25,9 +25,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -/** - * A representation of a WebVTT subtitle. - */ +/** A representation of a WebVTT subtitle. */ /* package */ final class WebvttSubtitle implements Subtitle { private final 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 6dc3b2f636..95df027ac2 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 class AdaptiveTrackSelection extends BaseTrackSelection { 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 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { } 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 19b1b03e59..91c4a79d3a 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.HashSet; 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 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNull; * * 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 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNull; * .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 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNull; * 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 class DefaultTrackSelector extends MappingTrackSelector { @SuppressWarnings({"deprecation"}) public ParametersBuilder() { super(); - setInitialValuesWithoutContext(); selectionOverrides = new SparseArray<>(); rendererDisabledFlags = new SparseBooleanArray(); + init(); } /** @@ -224,10 +207,9 @@ public class DefaultTrackSelector extends MappingTrackSelector { */ public ParametersBuilder(Context context) { super(context); - setInitialValuesWithoutContext(); selectionOverrides = new SparseArray<>(); rendererDisabledFlags = new SparseBooleanArray(); - setViewportSizeToPhysicalDisplaySize(context, /* viewportOrientationMayChange= */ true); + init(); } /** @@ -236,34 +218,19 @@ public class DefaultTrackSelector extends MappingTrackSelector { */ 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 @@ public class DefaultTrackSelector extends MappingTrackSelector { // Video - /** - * Equivalent to {@link #setMaxVideoSize setMaxVideoSize(1279, 719)}. - * - * @return This builder. - */ - public ParametersBuilder setMaxVideoSizeSd() { - return setMaxVideoSize(1279, 719); - } - - /** - * 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); - } - - /** - * 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 setMaxVideoSizeSd() { + super.setMaxVideoSizeSd(); 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 clearVideoSizeConstraints() { + super.clearVideoSizeConstraints(); 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 setMaxVideoSize( + int maxVideoWidth, int maxVideoHeight) { + super.setMaxVideoSize(maxVideoWidth, maxVideoHeight); 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 setMaxVideoFrameRate(int maxVideoFrameRate) { + super.setMaxVideoFrameRate(maxVideoFrameRate); 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 setMaxVideoBitrate(int maxVideoBitrate) { + super.setMaxVideoBitrate(maxVideoBitrate); 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 setMinVideoSize( + int minVideoWidth, int minVideoHeight) { + super.setMinVideoSize(minVideoWidth, minVideoHeight); + return this; + } + + @Override + public DefaultTrackSelector.ParametersBuilder setMinVideoFrameRate(int minVideoFrameRate) { + super.setMinVideoFrameRate(minVideoFrameRate); + return this; + } + + @Override + public DefaultTrackSelector.ParametersBuilder setMinVideoBitrate(int minVideoBitrate) { + super.setMinVideoBitrate(minVideoBitrate); return this; } @@ -407,70 +336,35 @@ public class DefaultTrackSelector extends MappingTrackSelector { 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); - } - - /** - * Equivalent to {@link #setViewportSize setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, - * true)}. - * - * @return This builder. - */ - public ParametersBuilder 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 ParametersBuilder setViewportSize( - int viewportWidth, int viewportHeight, boolean viewportOrientationMayChange) { - this.viewportWidth = viewportWidth; - this.viewportHeight = viewportHeight; - this.viewportOrientationMayChange = viewportOrientationMayChange; + super.setViewportSizeToPhysicalDisplaySize(context, 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 ParametersBuilder setPreferredVideoMimeType(@Nullable String mimeType) { - return mimeType == null ? setPreferredVideoMimeTypes() : setPreferredVideoMimeTypes(mimeType); + @Override + public ParametersBuilder clearViewportSizeConstraints() { + super.clearViewportSizeConstraints(); + 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 setViewportSize( + int viewportWidth, int viewportHeight, boolean viewportOrientationMayChange) { + super.setViewportSize(viewportWidth, viewportHeight, viewportOrientationMayChange); + return this; + } + + @Override + public ParametersBuilder setPreferredVideoMimeType(@Nullable String mimeType) { + super.setPreferredVideoMimeType(mimeType); + return this; + } + + @Override public ParametersBuilder setPreferredVideoMimeTypes(String... mimeTypes) { - preferredVideoMimeTypes = ImmutableList.copyOf(mimeTypes); + super.setPreferredVideoMimeTypes(mimeTypes); return this; } @@ -494,25 +388,15 @@ public class DefaultTrackSelector extends MappingTrackSelector { 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 class DefaultTrackSelector extends MappingTrackSelector { 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 class DefaultTrackSelector extends MappingTrackSelector { 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 class DefaultTrackSelector extends MappingTrackSelector { } /** 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 @@ public class DefaultTrackSelector extends MappingTrackSelector { } /** - * 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 class DefaultTrackSelector extends MappingTrackSelector { */ @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 class DefaultTrackSelector extends MappingTrackSelector { } // 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 class DefaultTrackSelector extends MappingTrackSelector { * 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 class DefaultTrackSelector extends MappingTrackSelector { * 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 class DefaultTrackSelector extends MappingTrackSelector { 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 class DefaultTrackSelector extends MappingTrackSelector { } /** 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 class DefaultTrackSelector extends MappingTrackSelector { 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 @@ public class DefaultTrackSelector extends MappingTrackSelector { @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 class DefaultTrackSelector extends MappingTrackSelector { 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 class DefaultTrackSelector extends MappingTrackSelector { 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 ee1fa2dcfe..ca4445362d 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 @@ public interface ExoTrackSelection extends TrackSelection { * 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 b630c127ac..7995526408 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 final class FixedTrackSelection extends BaseTrackSelection { 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 05ea4bb3c4..b73eb43c18 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 abstract class MappingTrackSelector extends TrackSelector { 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 abstract class MappingTrackSelector extends TrackSelector { 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 88719bc0ab..0000000000 --- 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 53ae2e9cd6..a0cc74588d 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 final class TrackSelectionUtil { } 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 59c5d5447b..88736c0a1c 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 @@ import com.google.android.exoplayer2.util.Assertions; * 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 @@ import com.google.android.exoplayer2.util.Assertions; * 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 @@ import com.google.android.exoplayer2.util.Assertions; * 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 @@ import com.google.android.exoplayer2.util.Assertions; */ 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 abstract class TrackSelector { * 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 4121a40875..7e815d259f 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 final class Allocation { 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 d508d375c3..6b9ddcc1da 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 05838c8a2d..f295fc5722 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.content.res.AssetManager; 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 final class AssetDataSource extends BaseDataSource { 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 final class AssetDataSource extends BaseDataSource { 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 final class AssetDataSource extends BaseDataSource { } @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 final class AssetDataSource extends BaseDataSource { 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 final class AssetDataSource extends BaseDataSource { 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 final class AssetDataSource extends BaseDataSource { } } } - } 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 c5b2893398..44e0bb4d4b 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 @@ import java.util.concurrent.CopyOnWriteArrayList; /** 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 63b8fd6e19..9471483419 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 final class ByteArrayDataSink implements DataSink { 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 24d2c728a1..a770c97ad7 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 static java.lang.Math.min; 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 final class ByteArrayDataSource extends BaseDataSource { 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 final class ByteArrayDataSource extends BaseDataSource { } @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 final class ByteArrayDataSource extends BaseDataSource { } 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 be93f883fe..3e53896ac0 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.content.res.AssetFileDescriptor; 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 @@ import java.nio.channels.FileChannel; /** 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 final class ContentDataSource extends BaseDataSource { 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 final class ContentDataSource extends BaseDataSource { 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 final class ContentDataSource extends BaseDataSource { // 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 final class ContentDataSource extends BaseDataSource { 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 final class ContentDataSource extends BaseDataSource { 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 final class ContentDataSource extends BaseDataSource { } @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 final class ContentDataSource extends BaseDataSource { 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 final class ContentDataSource extends BaseDataSource { 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 final class ContentDataSource extends BaseDataSource { 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 final class ContentDataSource extends BaseDataSource { } } } - } 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 0d1166e8a2..786d497730 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 android.util.Base64; 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 final class DataSchemeDataSource extends BaseDataSource { 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 final class DataSchemeDataSource extends BaseDataSource { } 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 final class DataSchemeDataSource extends BaseDataSource { } @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 594403c33d..af644a8c48 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 @@ import java.io.IOException; /** 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 c4296bd6f6..ddc68d137a 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 final class DataSourceInputStream extends InputStream { 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 @@ public final class DataSourceInputStream extends InputStream { 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 f354dc58ef..b79b66c930 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 final class DefaultAllocator implements Allocator { /** * 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 final class DefaultAllocator implements Allocator { 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 1c0b3f2642..7fd0928c61 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 final class DefaultBandwidthMeter implements BandwidthMeter, TransferList @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 cf89180b43..c2963f386e 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 final class DefaultDataSource implements DataSource { } @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 @@ public final class DefaultDataSource implements DataSource { 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 88b9112af8..ca309ad592 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 final class DefaultHttpDataSourceFactory extends BaseFactory { */ 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 091c57de10..8544a294a8 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 @@ package com.google.android.exoplayer2.upstream; 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 class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy { } /** - * 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; } - return C.TIME_UNSET; + // 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 null; } /** @@ -116,4 +129,19 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy { 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 5303e7f6eb..5f9860f2b5 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 final class DummyDataSource implements DataSource { } @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 7fba170f36..85284ee220 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 com.google.android.exoplayer2.util.Util.castNonNull; 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 @@ import java.io.RandomAccessFile; 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 final class FileDataSource extends BaseDataSource { @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 final class FileDataSource extends BaseDataSource { } @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 final class FileDataSource extends BaseDataSource { 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 @@ public final class FileDataSource extends BaseDataSource { + " 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 0102ea7871..0815f9ed5f 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 interface LoadErrorHandlingPolicy { } } - /** @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 @@ public interface LoadErrorHandlingPolicy { 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 d731455e51..8c9d9caff1 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 @@ import java.util.concurrent.atomic.AtomicBoolean; /** 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 final class Loader implements LoaderErrorThrower { 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 @@ public final class Loader implements LoaderErrorThrower { 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 final class Loader implements LoaderErrorThrower { 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 @@ public final class Loader implements LoaderErrorThrower { 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 @@ public final class Loader implements LoaderErrorThrower { private long getRetryDelayMillis() { return min((errorCount - 1) * 1000, 5000); } - } private static final class ReleaseTask implements Runnable { @@ -537,7 +528,5 @@ public final class Loader implements LoaderErrorThrower { 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 64d5938c89..eea3da8556 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 interface LoaderErrorThrower { // 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 c9701ed9c9..0296e093c1 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 @@ import java.util.Map; */ 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 final class ParsingLoadable implements Loadable { * @throws IOException If an error occurs reading data from the stream. */ T parse(Uri uri, InputStream inputStream) throws IOException; - } /** @@ -123,8 +120,8 @@ public final class ParsingLoadable implements Loadable { * @param type See {@link #type}. * @param parser Parses the object from the response. */ - public ParsingLoadable(DataSource dataSource, DataSpec dataSpec, 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 2f0d244307..33e57ee2d1 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 final class PriorityDataSource implements DataSource { } @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 final class PriorityDataSource implements DataSource { 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 cec2c9a79d..8f61480300 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 final class PriorityDataSourceFactory implements Factory { @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 ccdf7975a6..d896acef2f 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.net.Uri; 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 @@ import java.nio.channels.FileChannel; */ 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); } - public RawResourceDataSourceException(Throwable e) { - super(e); + /** @deprecated Use {@link #RawResourceDataSourceException(String, Throwable, int)}. */ + @Deprecated + public RawResourceDataSourceException(Throwable cause) { + super(cause, PlaybackException.ERROR_CODE_IO_UNSPECIFIED); + } + + /** 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 final class RawResourceDataSource extends BaseDataSource { 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 final class RawResourceDataSource extends BaseDataSource { 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 final class RawResourceDataSource extends BaseDataSource { 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 final class RawResourceDataSource extends BaseDataSource { 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 final class RawResourceDataSource extends BaseDataSource { // 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 final class RawResourceDataSource extends BaseDataSource { 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 final class RawResourceDataSource extends BaseDataSource { 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 final class RawResourceDataSource extends BaseDataSource { } @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 final class RawResourceDataSource extends BaseDataSource { 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 final class RawResourceDataSource extends BaseDataSource { 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 final class RawResourceDataSource extends BaseDataSource { 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 final class RawResourceDataSource extends BaseDataSource { } } } - } 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 958780cbc3..56301245e6 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 final class ResolvingDataSource implements DataSource { } @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 4340169f45..325865b26a 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 final class StatsDataSource implements DataSource { } @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 3ece5c1617..53e99cc346 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 final class TeeDataSource implements DataSource { } @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 final class TeeDataSource implements DataSource { } } } - } 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 2da837e788..df0ff1f1cc 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 static java.lang.Math.min; 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 static final class UdpDataSourceException extends DataSourceException { - public UdpDataSourceException(IOException cause) { - super(cause); + /** + * 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 final class UdpDataSource extends BaseDataSource { } 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 final class UdpDataSource extends BaseDataSource { } @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 final class UdpDataSource extends BaseDataSource { // 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 eb782bd334..cdce51aa1c 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 @@ import java.util.Set; /** * 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 @@ import java.util.Set; */ public interface Cache { - /** - * Listener of {@link Cache} events. - */ + /** Listener of {@link Cache} events. */ interface Listener { /** @@ -77,9 +75,7 @@ public interface Cache { 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 interface Cache { /** 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 76a833ddb5..7661171e4c 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 @@ public final class CacheDataSink implements DataSink { 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 @@ public final class CacheDataSink implements DataSink { } } } - } 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 efccb0cf78..931cdf4552 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 android.net.Uri; 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 final class CacheDataSource implements DataSource { 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 final class CacheDataSource implements DataSource { 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 final class CacheDataSource implements DataSource { } @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 final class CacheDataSource implements DataSource { 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 final class CacheDataSource implements DataSource { } 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 @@ public final class CacheDataSource implements DataSource { 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 2c51da8a8d..0f6159e349 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 final class CacheDataSourceFactory implements DataSource.Factory { 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 6ebfe01df4..6e59c4ecdc 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 e288a5258e..ec0ff46ac2 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 cba8f35009..ceb8ee7410 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 class CacheSpan implements Comparable { 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 ce69d5a46c..f8289809f8 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 d26e8036d7..3306b032ef 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 final class CachedRegionTracker implements Cache.Listener { } /** - * 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 final class CachedRegionTracker implements Cache.Listener { && 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 @@ public final class CachedRegionTracker implements Cache.Listener { 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 final class CachedRegionTracker implements Cache.Listener { 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 f6cac58997..7f84f80843 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 class ContentMetadataMutations { 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 706fa0d2c3..4b42146e97 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 final class DefaultContentMetadata implements ContentMetadata { @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 class DefaultContentMetadata implements ContentMetadata { @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 class DefaultContentMetadata implements ContentMetadata { } @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 class DefaultContentMetadata implements ContentMetadata { } @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 @@ public final class DefaultContentMetadata implements ContentMetadata { 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 db3cd2ef34..a4113de0df 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 final class NoOpCacheEvictor implements CacheEvictor { } @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 final class NoOpCacheEvictor implements CacheEvictor { 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 d02f7c0988..c9a70761b5 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 @@ import java.util.regex.Pattern; /* 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 @@ import java.util.regex.Pattern; 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 b29c5fac70..691e496c3b 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 final class AesCipherDataSink implements DataSink { } @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 43a100ca69..52352729eb 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 final class AesCipherDataSource implements DataSource { } @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 6df114442b..b539d31ab9 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 final class AesFlushingCipher { 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 @@ public final class AesFlushingCipher { 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 3418f46ed0..20681ee15a 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 @@ package com.google.android.exoplayer2.upstream.crypto; 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 @@ import androidx.annotation.Nullable; } 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 fa40f0f012..2e3b00044c 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 final class AtomicFile { /** * 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 6f35168d08..1200fcb70b 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 @@ public final class ColorParser { } 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 f7aac3bdae..9c11f37fb5 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 class DebugTextViewHelper implements Player.Listener, Runnable { @Override public final void onPlayWhenReadyChanged( - boolean playWhenReady, @Player.PlayWhenReadyChangeReason int playbackState) { + boolean playWhenReady, @Player.PlayWhenReadyChangeReason int reason) { updateAndPost(); } @@ -190,16 +190,23 @@ public class DebugTextViewHelper implements Player.Listener, Runnable { 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 60bd4f0c77..b4b7ec1a96 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 final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL } /** 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 12513f597a..8352c3aca8 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.os.SystemClock; 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.trackselection.TrackSelectionArray; 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 class EventLogger implements AnalyticsListener { } @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 class EventLogger implements AnalyticsListener { 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 class EventLogger implements AnalyticsListener { } @Override - public void onAudioEnabled(EventTime eventTime, DecoderCounters counters) { + public void onAudioEnabled(EventTime eventTime, DecoderCounters decoderCounters) { logd(eventTime, "audioEnabled"); } @@ -387,7 +373,7 @@ public class EventLogger implements AnalyticsListener { } @Override - public void onAudioDisabled(EventTime eventTime, DecoderCounters counters) { + public void onAudioDisabled(EventTime eventTime, DecoderCounters decoderCounters) { logd(eventTime, "audioDisabled"); } @@ -421,7 +407,7 @@ public class EventLogger implements AnalyticsListener { } @Override - public void onVideoEnabled(EventTime eventTime, DecoderCounters counters) { + public void onVideoEnabled(EventTime eventTime, DecoderCounters decoderCounters) { logd(eventTime, "videoEnabled"); } @@ -438,8 +424,8 @@ public class EventLogger implements AnalyticsListener { } @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 class EventLogger implements AnalyticsListener { } @Override - public void onVideoDisabled(EventTime eventTime, DecoderCounters counters) { + public void onVideoDisabled(EventTime eventTime, DecoderCounters decoderCounters) { logd(eventTime, "videoDisabled"); } @@ -517,8 +503,8 @@ public class EventLogger implements AnalyticsListener { } @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 @@ public class EventLogger implements AnalyticsListener { @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 @@ public class EventLogger implements AnalyticsListener { @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 be8ebe2f5c..f46f7a223b 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 final class LibraryLoader { } 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 48954cb9df..baa4802372 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 @@ import com.google.android.exoplayer2.PlaybackParameters; /** 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 fb43396156..58501d63cc 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 final class NetworkTypeObserver { 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 @@ public final class NetworkTypeObserver { @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 9021e26211..e380d84e35 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 @@ import java.util.PriorityQueue; */ 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 final class PriorityTaskManager { 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 9da5f09629..ac785295b9 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 @@ public abstract class RunnableFutureTask implements Runn // 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 829f252c22..ebe5c2a5f4 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 class SlidingPercentile { 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 class SlidingPercentile { 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 @@ public class SlidingPercentile { } } - /** - * 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 @@ public class SlidingPercentile { 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 87970d3c00..4c4d4d114b 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 final class StandaloneMediaClock implements MediaClock { 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 final class StandaloneMediaClock implements MediaClock { } } - /** - * 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 final class StandaloneMediaClock implements MediaClock { 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 ecc5c91ae3..40bd4de36b 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 @@ import androidx.annotation.Nullable; /** 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 final class UriUtil { } } + /** 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 @@ public final class UriUtil { 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 @@ public final class UriUtil { // 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 @@ public final class UriUtil { 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 d351442192..6628330338 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.ExoPlaybackException; 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 abstract class DecoderVideoRenderer extends BaseRenderer { } 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 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { } 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 a68a64b28d..51e23dbbba 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 @@ public final class DummySurface extends Surface { 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 816f2c9da6..e1eb1da0ba 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 class MediaCodecVideoRenderer extends MediaCodecRenderer { * @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 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { } @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 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { * @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 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { } 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 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { // 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 06d9e412e2..f47a76760f 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 final class VideoDecoderGLSurfaceView extends GLSurfaceView * @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 4a0a0fbe09..0386b7a17c 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 @@ import java.nio.ByteBuffer; /** 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 bb3b0b64c2..524460ab7a 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 final class VideoFrameReleaseHelper { private Display getDefaultDisplay() { return displayManager.getDisplay(Display.DEFAULT_DISPLAY); } - } /** @@ -579,21 +578,17 @@ public final class VideoFrameReleaseHelper { @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 @@ public final class VideoFrameReleaseHelper { 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 63370e7e54..116f6060ad 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 interface VideoRendererEventListener { } } } - } 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 c159fbee59..2348fcce23 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 @@ import androidx.annotation.BinderThread; // 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 b13b7fe5b1..1ff0c07490 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.android.exoplayer2.AudioFocusManager.PLAYER_COMMAND_WAI 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 class AudioFocusManagerTest { } @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 class AudioFocusManagerTest { } @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 class AudioFocusManagerTest { } @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 class AudioFocusManagerTest { } @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 867857cbe5..9be4c76e62 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 class DefaultMediaClockTest { @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 class DefaultMediaClockTest { @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 class DefaultMediaClockTest { } @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 class DefaultMediaClockTest { } @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 class DefaultMediaClockTest { } @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 class DefaultMediaClockTest { 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 6ad8b5c38a..69483fe91c 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_CHANGE_MEDIA_ITEMS; 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.atLeastOnce; 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; 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.Test; 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { .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 final class ExoPlayerTest { .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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 @@ public final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 @@ public final class ExoPlayerTest { // 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 @@ public final class ExoPlayerTest { // 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 final class ExoPlayerTest { 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 @@ public final class ExoPlayerTest { 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 @@ public final class ExoPlayerTest { } 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 @@ public final class ExoPlayerTest { 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 final class ExoPlayerTest { } @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 @@ public final class ExoPlayerTest { 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 8eaf476328..58d0d0c47b 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { /* 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,17 @@ public final class MediaPeriodQueueTest { /* 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); + /* adGroupIndex= */ 1, + AD_DURATION_US, + /* contentPositionUs= */ CONTENT_DURATION_US, + /* isFollowedByTransitionToSameStream= */ false); advance(); assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( /* periodUid= */ firstPeriodUid, @@ -199,6 +222,149 @@ public final class MediaPeriodQueueTest { /* 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= */ 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, + /* 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_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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { /* 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 final class MediaPeriodQueueTest { /* 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 @@ public final class MediaPeriodQueueTest { 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 @@ public final class MediaPeriodQueueTest { } 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 @@ public final class MediaPeriodQueueTest { long requestedContentPositionUs, long endPositionUs, long durationUs, + boolean isFollowedByTransitionToSameStream, boolean isLastInPeriod, boolean isLastInWindow, int nextAdGroupIndex) { @@ -595,13 +858,17 @@ public final class MediaPeriodQueueTest { 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 @@ public final class MediaPeriodQueueTest { 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 fb4ad4c648..4fb49e8b79 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.any; 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 @@ import org.robolectric.shadows.ShadowLooper; @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 class SimpleExoPlayerTest { 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 9545209805..549fa0cd5b 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.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.Renderer; @@ -730,7 +731,9 @@ public final class AnalyticsCollectorTest { 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 final class AnalyticsCollectorTest { 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 @@ public final class AnalyticsCollectorTest { 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 final class AnalyticsCollectorTest { // 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 @@ public final class AnalyticsCollectorTest { // 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 final class AnalyticsCollectorTest { 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 final class AnalyticsCollectorTest { 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 final class AnalyticsCollectorTest { 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 final class AnalyticsCollectorTest { } @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 final class AnalyticsCollectorTest { } @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 final class AnalyticsCollectorTest { } @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 final class AnalyticsCollectorTest { } @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 final class AnalyticsCollectorTest { } @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 f24e09346f..7a6fe531af 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 @@ public class DecoderAudioRendererTest { } 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 f1a4fb91f6..ae36f7edad 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.CURRENT_POSITION_NOT 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 final class DefaultAudioSinkTest { .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 final class DefaultAudioSinkTest { .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 c69deeaeef..9a26fdde87 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 androidx.test.ext.junit.runners.AndroidJUnit4; 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.ArgumentCaptor; 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 @@ public class MediaCodecAudioRendererTest { "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 9c14c37587..8176894702 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 final class SilenceSkippingAudioProcessorTest { // 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 final class SilenceSkippingAudioProcessorTest { // 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 @@ public final class SilenceSkippingAudioProcessorTest { * 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 46e179456c..5a2af2de84 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 final class SonicAudioProcessorTest { // 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 57fab8bb65..bed2e6f91f 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 final class ClearKeyUtilTest { // 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 d00d58c740..b4574a6b7f 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.After; 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 @@ import org.robolectric.shadows.ShadowMediaCodecList; /** 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 c98bd52da7..200b071e75 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.junit.runner.RunWith; 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 39055b573b..8a414ced43 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.Test; 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 fae8974c9d..081a6a5658 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.Test; 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 5e96ad2497..2d6bd31fdd 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.Test; 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 6bd5f711fc..773f274388 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.Test; 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 32f9e3e171..557f00f64d 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.junit.runner.RunWith; 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 56d50da290..88c2e14c61 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.Rule; 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 e00857cc92..9d2316e37f 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 com.google.android.exoplayer2.testutil.FakeClock; 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 c6206b2fc8..f7f9da385a 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 com.google.android.exoplayer2.testutil.FakeClock; 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 e0a6a32617..5ac951f51b 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.junit.runner.RunWith; 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 90c6d16cb4..9c29e27808 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.Test; 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 d1d9c38bf1..6391547433 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.Rule; 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 74a7d1c987..5dfeb04ff1 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.After; 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 class AsynchronousMediaCodecAdapterTest { /* 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 class AsynchronousMediaCodecAdapterTest { 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 b488403a68..8a25a66262 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 @@ public final class BatchBufferTest { 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 dcb1f634c9..b505ab62f6 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 final class SpliceInfoDecoderTest { @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 final class SpliceInfoDecoderTest { @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 final class SpliceInfoDecoderTest { 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 @@ public final class SpliceInfoDecoderTest { 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 c2f9ad07f7..a205496dd0 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { 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 final class CompositeSequenceableLoaderTest { // 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 final class CompositeSequenceableLoaderTest { 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 72a7c8c638..9be9445f47 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.source.ads.AdsMediaSource; 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 final class DefaultMediaSourceFactoryTest { 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 final class DefaultMediaSourceFactoryTest { 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 2ca6ee6343..7c437a0e02 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.TimeoutException; 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 final class ProgressiveMediaPeriodTest { } @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 8ce5c999f7..0b812ba14f 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 androidx.test.ext.junit.runners.AndroidJUnit4; 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 final class SampleQueueTest { 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 final class SampleQueueTest { // 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 @@ public final class SampleQueueTest { } } + 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 @@ public final class SampleQueueTest { (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 @@ public final class SampleQueueTest { 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 bfa4dbd049..c301337651 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 @@ public final class ShuffleOrderTest { 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 0000000000..1169522103 --- /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 0000000000..25379a816b --- /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 1d33c2834e..1d9f6e836c 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 static org.junit.Assert.assertThrows; 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 class CueTest { .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 3a06360b86..4b3b8cef64 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 @@ import org.junit.runner.RunWith; 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 final class SsaDecoderTest { 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 d068ade74b..67b4ec64b7 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 final class TtmlDecoderTest { 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 f9d12aefd1..ce57d720de 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 @@ public final class TtmlRenderUtilTest { 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 18a76c1a57..a81d1665e3 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 @@ import org.junit.runner.RunWith; 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 797a0b5d94..095dd02b66 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.Before; 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 final class CssParserTest { // 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 final class CssParserTest { 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 @@ public final class CssParserTest { 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 778820b451..a576958b88 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 final class WebvttCueParserTest { @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 final class WebvttCueParserTest { @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 final class WebvttCueParserTest { @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 eb565b09f5..4044d3d390 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 class WebvttDecoderTest { 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 29f3e69001..81959d35d8 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 static org.mockito.MockitoAnnotations.initMocks; 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.trackselection.TrackSelector.InvalidationLi 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 @@ public final class DefaultTrackSelectorTest { * 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 21c942974a..d770f27902 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 final class ByteArrayDataSourceTest { * @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 @@ public final class ByteArrayDataSourceTest { 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 @@ public final class ByteArrayDataSourceTest { 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 119d473e7d..297ae69e0b 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 static org.junit.Assert.fail; 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 final class DataSchemeDataSourceTest { 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 5bc3e4d04a..212b294455 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 final class DataSourceInputStreamTest { 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 final class DataSourceInputStreamTest { 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 e4c5c315f1..532be67521 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 final class DefaultBandwidthMeterTest { 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 final class DefaultBandwidthMeterTest { 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 final class DefaultBandwidthMeterTest { 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 final class DefaultBandwidthMeterTest { 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 final class DefaultBandwidthMeterTest { 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 final class DefaultBandwidthMeterTest { 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 final class DefaultBandwidthMeterTest { 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 final class DefaultBandwidthMeterTest { 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 final class DefaultBandwidthMeterTest { 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 02a7210683..16468d4155 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 final class DefaultLoadErrorHandlingPolicyTest { 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 @@ public final class DefaultLoadErrorHandlingPolicyTest { 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 360bc37c59..e16ef98056 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.DataSourceContractTest; 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 e6b44e9aa8..af43da8280 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 @@ public final class CacheDataSourceTest2 { 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 @@ public final class CacheDataSourceTest2 { 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 @@ public final class CacheDataSourceTest2 { // 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 @@ public final class CacheDataSourceTest2 { // 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 b094f332de..1ff7ea81d7 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 final class CacheWriterTest { @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 final class CacheWriterTest { @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 1237d3a312..33e6576b73 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 @@ import org.junit.runner.RunWith; 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 4984e71a3e..ffe5dbdb87 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 class LeastRecentlyUsedCacheEvictorTest { 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 fa56c31a89..b0641a705c 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 class SimpleCacheSpanTest { + "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 @@ public class SimpleCacheSpanTest { 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 9af0710e9b..2811b0eada 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 class AesFlushingCipherTest { 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 cab14c2c31..dd5ccac8cd 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 @@ public final class AtomicFileTest { 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 c2f165dec1..da9ddbe491 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 final class ColorParserTest { @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 6ab273bf5b..bc1cc8a5cb 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 final class ReusableBufferedOutputStreamTest { 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 6d1c27c518..02741eb16f 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 final class UriUtilTest { 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 final class UriUtilTest { 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 0000000000..7971085933 --- /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 d93915f761..128334ced2 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 @@ public interface DashChunkSource extends ChunkSource { /** * @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 @@ public interface DashChunkSource extends ChunkSource { 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 6cf10b3578..38205a4621 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; @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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; public DashMediaPeriod( int id, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, DashChunkSource.Factory chunkSourceFactory, @Nullable TransferListener transferListener, @@ -121,6 +123,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; PlayerEmsgCallback playerEmsgCallback) { this.id = id; this.manifest = manifest; + this.baseUrlExclusionList = baseUrlExclusionList; this.periodIndex = periodIndex; this.chunkSourceFactory = chunkSourceFactory; this.transferListener = transferListener; @@ -766,6 +769,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 4136fab1bf..b4ac738372 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 @@ package com.google.android.exoplayer2.source.dash; 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 final class DashMediaSource extends BaseMediaSource { 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 @@ public final class DashMediaSource extends BaseMediaSource { 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 final class DashMediaSource extends BaseMediaSource { // 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 final class DashMediaSource extends BaseMediaSource { } @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 @@ public final class DashMediaSource extends BaseMediaSource { expiredManifestPublishTimeUs = C.TIME_UNSET; firstPeriodId = 0; periodsById.clear(); + baseUrlExclusionList.reset(); drmSessionManager.release(); } @@ -648,8 +639,8 @@ public final class DashMediaSource extends BaseMediaSource { // 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 @@ public final class DashMediaSource extends BaseMediaSource { 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 @@ public final class DashMediaSource extends BaseMediaSource { 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 @@ public final class DashMediaSource extends BaseMediaSource { } } - 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 @@ public final class DashMediaSource extends BaseMediaSource { 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 final class DashMediaSource extends BaseMediaSource { } @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 final class DashMediaSource extends BaseMediaSource { @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 @@ public final class DashMediaSource extends BaseMediaSource { return windowDefaultStartPositionUs; } long segmentNum = snapIndex.getSegmentNum(defaultStartPositionInPeriodUs, periodDurationUs); - return windowDefaultStartPositionUs + snapIndex.getTimeUs(segmentNum) + return windowDefaultStartPositionUs + + snapIndex.getTimeUs(segmentNum) - defaultStartPositionInPeriodUs; } @@ -1394,7 +1395,6 @@ public final class DashMediaSource extends BaseMediaSource { int errorCount) { return onManifestLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error, errorCount); } - } private final class UtcTimestampCallback implements Loader.Callback> { @@ -1423,7 +1423,6 @@ public final class DashMediaSource extends BaseMediaSource { int errorCount) { return onUtcTimestampLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error); } - } private static final class XsDateTimeParser implements ParsingLoadable.Parser { @@ -1433,7 +1432,6 @@ public final class DashMediaSource extends BaseMediaSource { 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 final class DashMediaSource extends BaseMediaSource { 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 final class DashMediaSource extends BaseMediaSource { } 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 17ee580036..9ca1c176fe 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,6 +46,29 @@ public final class DashUtil { /** * Builds a {@link DataSpec} for a given {@link RangedUri} belonging to {@link Representation}. * + * @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( + String baseUrl, RangedUri requestUri, @Nullable String cacheKey, int flags) { + return new DataSpec.Builder() + .setUri(requestUri.resolveUri(baseUrl)) + .setPosition(requestUri.start) + .setLength(requestUri.length) + .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 @@ -54,13 +77,8 @@ public final class DashUtil { */ public static DataSpec buildDataSpec( Representation representation, RangedUri requestUri, int flags) { - return new DataSpec.Builder() - .setUri(requestUri.resolveUri(representation.baseUrl)) - .setPosition(requestUri.start) - .setLength(requestUri.length) - .setKey(representation.getCacheKey()) - .setFlags(flags) - .build(); + return buildDataSpec( + representation.baseUrls.get(0).url, requestUri, representation.getCacheKey(), flags); } /** @@ -96,6 +114,7 @@ public final class DashUtil { } } Format manifestFormat = representation.format; + @Nullable Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation); return sampleFormat == null ? manifestFormat @@ -109,24 +128,46 @@ public final class DashUtil { * @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,6 +176,38 @@ public final class DashUtil { * @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, int baseUrlIndex) + throws IOException { + if (representation.getInitializationUri() == null) { + return null; + } + ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format); + try { + 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. @@ -142,16 +215,7 @@ public final class DashUtil { @Nullable public static ChunkIndex loadChunkIndex( DataSource dataSource, int trackType, Representation representation) throws IOException { - if (representation.getInitializationUri() == null) { - return null; - } - ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format); - try { - loadInitializationData(chunkExtractor, dataSource, representation, /* loadIndex= */ true); - } finally { - chunkExtractor.release(); - } - return chunkExtractor.getChunkIndex(); + return loadChunkIndex(dataSource, trackType, representation, /* baseUrlIndex= */ 0); } /** @@ -161,6 +225,7 @@ public final class DashUtil { * @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 @@ public final class DashUtil { 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 1d46d08422..e894e07c3d 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 final class DashWrappingSegmentIndex implements DashSegmentIndex { 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 45806d390a..e5fd60a2b0 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.MediaChunkIterator; 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.trackselection.ExoTrackSelection; 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 class DefaultDashChunkSource implements DashChunkSource { public DashChunkSource createDashChunkSource( LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, int[] adaptationSetIndices, ExoTrackSelection trackSelection, @@ -116,6 +119,7 @@ public class DefaultDashChunkSource implements DashChunkSource { chunkExtractorFactory, manifestLoaderErrorThrower, manifest, + baseUrlExclusionList, periodIndex, adaptationSetIndices, trackSelection, @@ -127,10 +131,10 @@ public class DefaultDashChunkSource implements DashChunkSource { 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 class DefaultDashChunkSource implements DashChunkSource { * 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 class DefaultDashChunkSource implements DashChunkSource { ChunkExtractor.Factory chunkExtractorFactory, LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, + BaseUrlExclusionList baseUrlExclusionList, int periodIndex, int[] adaptationSetIndices, ExoTrackSelection trackSelection, @@ -183,6 +189,7 @@ public class DefaultDashChunkSource implements DashChunkSource { @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 class DefaultDashChunkSource implements DashChunkSource { 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 class DefaultDashChunkSource implements DashChunkSource { } 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 class DefaultDashChunkSource implements DashChunkSource { @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 class DefaultDashChunkSource implements DashChunkSource { 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 class DefaultDashChunkSource implements DashChunkSource { } } } - 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 class DefaultDashChunkSource implements DashChunkSource { // 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 @@ public class DefaultDashChunkSource implements DashChunkSource { 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 @@ public class DefaultDashChunkSource implements DashChunkSource { 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 @@ public class DefaultDashChunkSource implements DashChunkSource { 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 @@ public class DefaultDashChunkSource implements DashChunkSource { 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 class DefaultDashChunkSource implements DashChunkSource { 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 @@ public class DefaultDashChunkSource implements DashChunkSource { @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 @@ public class DefaultDashChunkSource implements DashChunkSource { /* 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 @@ public class DefaultDashChunkSource implements DashChunkSource { /* 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 @@ public class DefaultDashChunkSource implements DashChunkSource { - 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 1abe48a047..19816a4496 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 com.google.android.exoplayer2.util.Util; 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 @@ import java.io.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 @@ import java.io.IOException; 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 b9c1ae995c..f368bdc071 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 final class PlayerEmsgHandler implements Handler.Callback { @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 316b98ebcd..48b228e993 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 @@ import java.util.List; /** 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 0000000000..1792afd905 --- /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 b1b61fde5f..06699afa7a 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 class DashManifest implements FilterableManifest { 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 @@ public class DashManifest implements FilterableManifest { 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 bf72353cfc..f58e428a6f 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.android.exoplayer2.util.XmlPullParserUtil; 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 class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler Pair periodWithDurationMs = parsePeriod( xpp, - baseUrl, + !baseUrls.isEmpty() ? baseUrls : parentBaseUrls, nextPeriodStartMs, baseUrlAvailabilityTimeOffsetUs, availabilityStartTime, @@ -165,12 +169,13 @@ public class DashManifestParser extends DefaultHandler // 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 @@ public class DashManifestParser extends DefaultHandler // 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 @@ public class DashManifestParser extends DefaultHandler protected Pair parsePeriod( XmlPullParser xpp, - String baseUrl, + List parentBaseUrls, long defaultStartMs, long baseUrlAvailabilityTimeOffsetUs, long availabilityStartTimeMs, @@ -286,6 +292,7 @@ public class DashManifestParser extends DefaultHandler @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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler protected AdaptationSet parseAdaptationSet( XmlPullParser xpp, - String baseUrl, + List parentBaseUrls, @Nullable SegmentBase segmentBase, long periodDurationMs, long baseUrlAvailabilityTimeOffsetUs, @@ -389,6 +396,7 @@ public class DashManifestParser extends DefaultHandler ArrayList essentialProperties = new ArrayList<>(); ArrayList supplementalProperties = new ArrayList<>(); List representationInfos = new ArrayList<>(); + ArrayList baseUrls = new ArrayList<>(); boolean seenFirstBaseUrl = false; do { @@ -397,9 +405,9 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler RepresentationInfo representationInfo = parseRepresentation( xpp, - baseUrl, + !baseUrls.isEmpty() ? baseUrls : parentBaseUrls, mimeType, codecs, width, @@ -523,10 +531,14 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler protected RepresentationInfo parseRepresentation( XmlPullParser xpp, - String baseUrl, + List parentBaseUrls, @Nullable String adaptationSetMimeType, @Nullable String adaptationSetCodecs, int adaptationSetWidth, @@ -657,6 +669,7 @@ public class DashManifestParser extends DefaultHandler ArrayList essentialProperties = new ArrayList<>(adaptationSetEssentialProperties); ArrayList supplementalProperties = new ArrayList<>(adaptationSetSupplementalProperties); + ArrayList baseUrls = new ArrayList<>(); boolean seenFirstBaseUrl = false; do { @@ -665,9 +678,9 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler return Representation.newInstance( representationInfo.revisionId, formatBuilder.build(), - representationInfo.baseUrl, + representationInfo.baseUrls, representationInfo.segmentBase, inbandEventStreams); } @@ -831,8 +850,9 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler } } 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler * 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 class DashManifestParser extends DefaultHandler } } - /** - * 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 @@ public class DashManifestParser extends DefaultHandler /** * 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 @@ public class DashManifestParser extends DefaultHandler 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 55dba54db1..23c8ee368e 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 final class Descriptor { 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 178693fe04..ddc2fe5d1a 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 @@ import com.google.android.exoplayer2.metadata.emsg.EventMessage; /** 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 final class EventStream { 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 a2396e2533..449803ea1e 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 @@ import java.util.List; /** 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 class Period { * @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 class Period { } 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 60975dd54b..1637b2625a 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 @@ import com.google.android.exoplayer2.util.UriUtil; /** 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 final class RangedUri { 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 226ae84c51..af9771ef14 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.Format; 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 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. * @param inbandEventStreams The in-band event streams in the representation. May be null. * @return The constructed instance. @@ -85,16 +80,11 @@ public abstract class Representation { 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 abstract class 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 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 abstract class Representation { 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 abstract class Representation { 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 abstract class Representation { @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 abstract class Representation { 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 abstract class Representation { 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 abstract class Representation { 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 abstract class 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 abstract class Representation { // 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 abstract class Representation { } @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 abstract class Representation { 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 20f45b8036..754d5fc99d 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 abstract class SegmentBase { 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 abstract class SegmentBase { ? 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 abstract class SegmentBase { public boolean isExplicit() { return true; } - } /** A {@link MultiSegmentBase} that uses a SegmentTemplate to define its segments. */ @@ -434,8 +426,9 @@ public abstract class SegmentBase { @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 abstract class SegmentBase { } 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 abstract class SegmentBase { 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 a5806450a3..77f189f5b1 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 @@ package com.google.android.exoplayer2.source.dash.manifest; 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 @@ import com.google.android.exoplayer2.source.dash.DashSegmentIndex; 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 fbf06c5885..cc3597a33a 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 final class UrlTemplate { 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 final class UrlTemplate { /** * 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 final class UrlTemplate { * @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 @@ public final class UrlTemplate { } 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 9508623c9d..7deb92e66c 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 final class UtcTimingElement { 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 ed195ec417..2029b370de 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; */ 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 final class DashDownloader extends SegmentDownloader { 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 @@ public final class DashDownloader extends SegmentDownloader { 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 0000000000..cb75903c81 --- /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 99fd169437..fd55087b47 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.io.InputStream; 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 @@ public final class DashMediaPeriodTest { 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 d1269e18a1..e9079e91d2 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 @@ package com.google.android.exoplayer2.source.dash; 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.CountDownLatch; 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 final class DashMediaSourceTest { 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 188d1b2a18..1eb422d27c 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.Format; 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 @@ public final class DashUtilTest { .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 e403482b6c..1308416f18 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 class DefaultDashChunkSourceTest { 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 class DefaultDashChunkSourceTest { 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 class DefaultDashChunkSourceTest { 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 ab7f456c55..1e64b8d7a4 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.source.MediaSource; 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 348290eb69..7dfa4e6597 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 com.google.android.exoplayer2.util.MimeTypes; 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 final class EventSampleStreamTest { */ @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 final class EventSampleStreamTest { */ @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 final class EventSampleStreamTest { */ @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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 final class EventSampleStreamTest { 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 @@ public final class EventSampleStreamTest { 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 372fa07646..9014a8c40b 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 com.google.android.exoplayer2.trackselection.DefaultTrackSelector; 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 24ae834f33..8c3ea0c127 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.testutil.TestUtil; 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 class DashManifestParserTest { (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 class DashManifestParserTest { 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 7b3b3cab51..0b3a3efbbb 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 androidx.test.ext.junit.runners.AndroidJUnit4; 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 @@ public class DashManifestTest { } 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 44af227d96..486ab08cd1 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 androidx.test.ext.junit.runners.AndroidJUnit4; 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 91ddfbbde9..49346c4f98 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 androidx.test.ext.junit.runners.AndroidJUnit4; 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 6736840d82..057844d848 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 static org.junit.Assert.fail; 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 d835b85725..e47137baf9 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.Test; 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 bfc11cb47a..b7323c49a3 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.testutil.FakeDataSource; 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 6bdc84438b..29102dfe3e 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.Ignore; 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 98a7f6e887..e62a644af5 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.Before; 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 28e0ccdc0a..fa2a23ee20 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 525b335f13..caf72df415 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 @@ public final class CeaUtil { } 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 3a783e4df9..8291ed1ea4 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 @@ import java.util.Arrays; /** 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 38844f61c7..e04307bad7 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 final class DefaultExtractorInput implements ExtractorInput { } @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 final class DefaultExtractorInput implements ExtractorInput { 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 @@ public final class DefaultExtractorInput implements ExtractorInput { 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 ff887000a3..0cbde6ab86 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 63870282b5..21fb7f1269 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 6799ca6de1..3dc9e0b15b 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 @@ import java.io.InputStream; * 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 @@ import java.io.InputStream; * 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 @@ public interface ExtractorInput extends DataReader { */ 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 @@ public interface ExtractorInput extends DataReader { * @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 09f5fa493d..bffda30d0b 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 interface ExtractorOutput { * @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 3eca5c776b..54cc61f2ef 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 fc1b121326..846dd05f14 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 final class FlacFrameReader { 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 922ef0f3da..01d2def12d 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 final class FlacMetadataReader { 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 final class FlacMetadataReader { 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 2a9726fac2..c70202d137 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 class ForwardingExtractorInput implements ExtractorInput { } @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 09d2fd1f88..0bf6b146d5 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 @@ public final class GaplessInfoHolder { 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 e4ac523350..94ca7282d3 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 @@ package com.google.android.exoplayer2.extractor; /** 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 a461f4b700..1a58d232f0 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 @@ import java.util.Arrays; /** 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 @@ public interface TrackOutput { 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 @@ public interface TrackOutput { * @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 interface TrackOutput { 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 interface TrackOutput { 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 @@ public interface TrackOutput { * @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 7ec9c93832..56f419a184 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 final class VorbisBitArray { 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 final class VorbisBitArray { 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 final class VorbisBitArray { 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 ede2ab39e9..5fbd0e4ae4 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 final class VorbisUtil { /** * 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 final class VorbisUtil { 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 final class VorbisUtil { 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 final class VorbisUtil { 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 final class VorbisUtil { 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 final class VorbisUtil { 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 final class VorbisUtil { 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 @@ public final class VorbisUtil { 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 @@ public final class VorbisUtil { 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 @@ public final class VorbisUtil { 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 @@ public final class VorbisUtil { 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 @@ public final class VorbisUtil { } 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 @@ public final class VorbisUtil { } } 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 @@ public final class VorbisUtil { 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 @@ public final class VorbisUtil { 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 4d8ef18448..92821daf13 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 final class AmrExtractor implements Extractor { } @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 final class AmrExtractor implements Extractor { 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 @@ public final class AmrExtractor implements Extractor { 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 @@ public final class AmrExtractor implements Extractor { 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 d6eb4772c4..2b7c474b01 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 0ca65e4de5..124d62dd40 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.MimeTypes; 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 2fdaf7dc46..ffb85d07f0 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 @@ public final class FlvExtractor implements Extractor { 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 f0b4efb106..696b38c8a5 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.HashMap; 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 48914b7c2c..8d56951b20 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 6ab4da1acf..03ff74c39d 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.NalUnitUtil; 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 @@ import com.google.android.exoplayer2.video.AvcConfig; 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 @@ import com.google.android.exoplayer2.video.AvcConfig; 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 777126905a..a985ec83ee 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.TrackOutput; 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 @@ public final class JpegExtractor implements Extractor { 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 0972c00567..17fa7756ab 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 @@ import org.xmlpull.v1.XmlPullParserFactory; 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 754cd7a4c2..de4c9e23c6 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 java.util.ArrayDeque; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 7291ae9c83..458b2e87e3 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 fc32fba4f7..c19906a93a 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 @@ import java.io.IOException; /** * 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 c3f3e5e901..e1c68726b3 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { } } 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { @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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { // 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 @@ public class MatroskaExtractor implements Extractor { */ 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 class MatroskaExtractor implements Extractor { 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 class MatroskaExtractor implements Extractor { 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 class MatroskaExtractor implements Extractor { || 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 class MatroskaExtractor implements Extractor { @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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { 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 @@ public class MatroskaExtractor implements Extractor { @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 415d3d4546..f36adbed66 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 @@ import java.io.IOException; */ /* 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 @@ import java.io.IOException; 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 @@ import java.io.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 6b244de72d..a6ee6d9cc1 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 com.google.android.exoplayer2.extractor.ExtractorInput; 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 @@ import java.io.IOException; * *

    {@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 @@ import java.io.IOException; 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 @@ import java.io.IOException; 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 @@ import java.io.IOException; * 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 @@ import java.io.IOException; * @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 @@ import java.io.IOException; } 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 21b7c8544f..468e31e30a 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 final class Mp3Extractor implements Extractor { 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 @@ public final class Mp3Extractor implements Extractor { // 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 @@ public final class Mp3Extractor implements Extractor { 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 @@ public final class Mp3Extractor implements Extractor { 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 daf5265ddd..f2532863c4 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 @@ import com.google.android.exoplayer2.util.Util; 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 d95721be5d..51950e6282 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 @@ import com.google.android.exoplayer2.util.Util; // 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 @@ import com.google.android.exoplayer2.util.Util; 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 @@ import com.google.android.exoplayer2.util.Util; 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 @@ import com.google.android.exoplayer2.util.Util; 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 273421a813..a85d928f04 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 @@ import java.util.List; @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 @@ import java.util.List; @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 @@ import java.util.List; @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 @@ import java.util.List; 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 @@ import java.util.List; 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 @@ import java.util.List; @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 @@ import java.util.List; * @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 dea3113b61..f6ed6f7796 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 @@ package com.google.android.exoplayer2.extractor.mp4; 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.Ac3Util; 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 java.util.List; 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; - - @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_soun = 0x736f756e; - - @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_text = 0x74657874; - - @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_sbtl = 0x7362746c; - - @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_subt = 0x73756274; - @SuppressWarnings("ConstantCaseForConstants") private static final int TYPE_clcp = 0x636c6370; + @SuppressWarnings("ConstantCaseForConstants") + private static final int TYPE_mdta = 0x6d647461; + @SuppressWarnings("ConstantCaseForConstants") private static final int TYPE_meta = 0x6d657461; @SuppressWarnings("ConstantCaseForConstants") - private static final int TYPE_mdta = 0x6d647461; + 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_soun = 0x736f756e; + + @SuppressWarnings("ConstantCaseForConstants") + private static final int TYPE_subt = 0x73756274; + + @SuppressWarnings("ConstantCaseForConstants") + private static final int TYPE_text = 0x74657874; + + @SuppressWarnings("ConstantCaseForConstants") + 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } } } - 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; && 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; || 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; || 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; || 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; @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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; // 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; .setStereoMode(stereoMode) .setInitializationData(initializationData) .setDrmInitData(drmInitData) + .setColorInfo(colorInfo) .build(); } @@ -1253,14 +1318,14 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } } 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; * 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; */ @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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; @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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } } - /** - * 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } } } - } 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 1ec0237356..f1f6f57774 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 @@ package com.google.android.exoplayer2.extractor.mp4; 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 5ebc0a3587..ae16c8107f 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 @@ import com.google.android.exoplayer2.util.Util; */ /* 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 @@ import com.google.android.exoplayer2.util.Util; 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 @@ import com.google.android.exoplayer2.util.Util; * @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 ef71d82559..b72159be1d 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 class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { } 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 @@ public class FragmentedMp4Extractor implements Extractor { } } 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { } } - /** - * 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 @@ public class FragmentedMp4Extractor implements Extractor { } } - 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { ((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 @@ public class FragmentedMp4Extractor implements Extractor { // 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { } 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 @@ public class FragmentedMp4Extractor implements Extractor { // 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 @@ public class FragmentedMp4Extractor implements Extractor { 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 @@ public class FragmentedMp4Extractor implements Extractor { /** 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 class FragmentedMp4Extractor implements Extractor { 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 class FragmentedMp4Extractor implements Extractor { : 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 a5470dace6..9aa19cff56 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 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; 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 092dbae496..d542fa8545 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 @@ public final class Mp4Extractor implements Extractor, SeekMap { } 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 @@ public final class Mp4Extractor implements Extractor, SeekMap { } } - /** - * 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 @@ public final class Mp4Extractor implements Extractor, SeekMap { 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 @@ public final class Mp4Extractor implements Extractor, SeekMap { 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 @@ public final class Mp4Extractor implements Extractor, SeekMap { 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 final class Mp4Extractor implements Extractor, SeekMap { 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 c47ca8d6ba..3be0946e94 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 final class PsshAtomUtil { /** * 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 final class PsshAtomUtil { 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 ccf5180f41..36586e7059 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 @@ import java.util.List; 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 @@ import java.util.List; 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 @@ import java.util.List; 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 5a8b467cc2..2c4a847ee5 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 @@ import java.io.IOException; 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 @@ import java.io.IOException; 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 1e917f825d..3771be0952 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 final class Track { */ @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 986c5bb255..aed1bcf48f 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 final class 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 @@ public final class TrackEncryptionBox { 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 92ce551f48..5a1fc6e0d8 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 com.google.android.exoplayer2.util.ParsableByteArray; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * 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 ca500b2931..5104aeb209 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.C; 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 @@ import com.google.android.exoplayer2.util.Util; } 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 a86b4350c0..fd7688baad 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 com.google.android.exoplayer2.util.Util; 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 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; @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 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; 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 49c8e2fb3b..32fb588c75 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 class OggExtractor implements Extractor { 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 @@ public class OggExtractor implements Extractor { 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 dcca44b3d8..b31d3769b2 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 com.google.android.exoplayer2.util.ParsableByteArray; 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 @@ import java.util.Arrays; 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 @@ import java.util.Arrays; 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 @@ import java.util.Arrays; } 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 70a1f22f54..306e64f559 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.Assertions; 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 @@ import java.io.IOException; 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 @@ import java.io.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 08b6fb8cae..32791c33d5 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.Arrays; 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 f160655459..7b0871c151 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 7e7b6eb84d..607bffe858 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.ArrayList; 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 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; 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 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; 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 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; 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 d9339fa689..a1c4977745 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 @@ public final class RawCcExtractor implements Extractor { } 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 94a277582d..65f0f3a60a 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 final class Ac3Extractor implements Extractor { 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 2de59a5a07..262dab358c 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 final class Ac3Reader implements ElementaryStreamReader { } @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 @@ public final class Ac3Reader implements ElementaryStreamReader { // 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 0f088836d1..6581ecefdb 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 final class Ac4Reader implements ElementaryStreamReader { } @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 7c93c210f3..f4fc317fdc 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 @@ public final class AdtsExtractor implements Extractor { // 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 13d76134da..0e1a1ed783 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 @@ public final class AdtsReader implements ElementaryStreamReader { 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 @@ public final class AdtsReader implements ElementaryStreamReader { } /** - * 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 @@ public final class AdtsReader implements ElementaryStreamReader { * @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 @@ public final class AdtsReader implements ElementaryStreamReader { 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 @@ public final class AdtsReader implements ElementaryStreamReader { 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 6b5579e3a9..3d9c2b04c5 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 final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact * @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 final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact 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 final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact 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 final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact 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 3ffc44b730..0a10aa7790 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 @@ public final class DtsReader implements ElementaryStreamReader { 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 592e28ba57..34552c3089 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 @@ public final class DvbSubtitleReader implements ElementaryStreamReader { 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 a876959723..48227d6670 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 @@ import com.google.android.exoplayer2.util.ParsableByteArray; /** 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 de9756e155..c42c3557e8 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 final class H262Reader implements ElementaryStreamReader { 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 @@ public final class H262Reader implements ElementaryStreamReader { 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 final class H262Reader implements ElementaryStreamReader { 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 final class H262Reader implements ElementaryStreamReader { * @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 final class H262Reader implements ElementaryStreamReader { 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 116bcfef29..6790747ac9 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 final class H264Reader implements ElementaryStreamReader { // 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 @@ public final class H264Reader implements ElementaryStreamReader { 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 final class H264Reader implements ElementaryStreamReader { 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 final class H264Reader implements ElementaryStreamReader { } 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 final class H264Reader implements ElementaryStreamReader { 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 dd5dcc1782..9dccd88280 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 final class H265Reader implements ElementaryStreamReader { // 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 @@ public final class H265Reader implements ElementaryStreamReader { .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 66eb67f16c..74937ddce9 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 final class Id3Reader implements ElementaryStreamReader { 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 final class Id3Reader implements ElementaryStreamReader { 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 64f56f6455..8cd33f2851 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 @@ public final class LatmReader implements ElementaryStreamReader { 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 @@ public final class LatmReader implements ElementaryStreamReader { 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 @@ public final class LatmReader implements ElementaryStreamReader { 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 @@ public final class LatmReader implements ElementaryStreamReader { 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 @@ public final class LatmReader implements ElementaryStreamReader { } while (tmp == 255); return muxSlotLengthBytes; } else { - throw new ParserException(); + throw ParserException.createForMalformedContainer(/* message= */ null, /* cause= */ null); } } @@ -319,5 +319,4 @@ public final class LatmReader implements ElementaryStreamReader { 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 f65f515a9a..a3e0712332 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 final class MpegAudioReader implements ElementaryStreamReader { /** * 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 ece2fdf767..04081c7cdf 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 com.google.android.exoplayer2.util.Assertions; 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 @@ import java.util.Arrays; 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 @@ import java.util.Arrays; /** * 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 @@ import java.util.Arrays; 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 72667e2a3f..111cfd8750 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 final class PassthroughSectionPayloadReader implements SectionPayloadRead @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 final class PassthroughSectionPayloadReader implements SectionPayloadRead } 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 eb3606a8b0..7b4ca00cef 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 final class PesReader implements TsPayloadReader { } @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 @@ public final class PesReader implements TsPayloadReader { 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 @@ public final class PesReader implements TsPayloadReader { 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 f8aed61321..4611a25825 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 final class PsExtractor implements Extractor { 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 final class PsExtractor implements Extractor { 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 final class PsExtractor implements Extractor { @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 final class PsExtractor implements Extractor { 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 @@ public final class PsExtractor implements Extractor { } } - /** - * 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 final class PsExtractor implements Extractor { /** * 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 @@ public final class PsExtractor implements Extractor { 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 4bd5867565..40e15fa08d 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 @@ public interface SectionPayloadReader { * 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 3b2bd4ce89..4a73799c07 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 final class SectionReader implements TsPayloadReader { } @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 final class SectionReader implements TsPayloadReader { } } } - } 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 9fff73315c..b3229db262 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 final class SeiReader { 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 05577ca242..6f2406bf2c 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 @@ import java.io.IOException; } 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 325f05ff2b..1ff9c06e79 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 final class TsExtractor implements Extractor { 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 @@ public final class TsExtractor implements Extractor { 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 @@ public final class TsExtractor implements Extractor { 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 final class TsExtractor implements Extractor { } @Override - public void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, + public void init( + TimestampAdjuster timestampAdjuster, + ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { // Do nothing. } @@ -528,12 +532,9 @@ public final class TsExtractor implements Extractor { 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 final class TsExtractor implements Extractor { } @Override - public void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorOutput, + public void init( + TimestampAdjuster timestampAdjuster, + ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { // Do nothing. } @@ -577,8 +580,8 @@ public final class TsExtractor implements Extractor { 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 final class TsExtractor implements Extractor { // 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 final class TsExtractor implements Extractor { @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 @@ public final class TsExtractor implements Extractor { 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 @@ public final class TsExtractor implements Extractor { 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 581f4ec4ea..34405a7a1a 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 @@ import java.util.List; /** 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 @@ public interface TsPayloadReader { 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 interface TsPayloadReader { : Collections.unmodifiableList(dvbSubtitleInfos); this.descriptorBytes = descriptorBytes; } - } /** @@ -111,12 +106,9 @@ public interface TsPayloadReader { 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 interface TsPayloadReader { * 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 @@ public interface TsPayloadReader { throw new IllegalStateException("generateNewId() must be called before retrieving ids."); } } - } /** @@ -212,7 +202,9 @@ public interface TsPayloadReader { * @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 bb4734f183..c1dd2a6ddc 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 final class WavExtractor implements Extractor { 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 final class WavExtractor implements Extractor { @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 final class WavExtractor implements Extractor { 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 final class WavExtractor implements Extractor { 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 af8ede69aa..f794933d16 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 @@ import java.io.IOException; 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 4d70fe3b69..bbf72027f7 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 androidx.test.ext.junit.runners.AndroidJUnit4; 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 646c378eb4..550b7515e0 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.io.IOException; 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 class DefaultExtractorInputTest { 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 @@ public class DefaultExtractorInputTest { 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 @@ public class DefaultExtractorInputTest { 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 1c6ce7b70c..6ad0554d07 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.List; 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 caf184a119..4d3d8a7472 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 androidx.test.ext.junit.runners.AndroidJUnit4; 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 final class ExtractorTest { 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 8959caa323..6734face12 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.io.EOFException; 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 75ef1a201e..3f37e5ca7b 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 com.google.android.exoplayer2.util.ParsableByteArray; 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 @@ import org.junit.runner.RunWith; * 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 1648d548d2..046b810a82 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.io.IOException; 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 @@ import org.junit.runner.RunWith; * 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 9c6b63ee0a..3a4d515d20 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.io.IOException; 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 e0cf957a38..4a252fa097 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 com.google.android.exoplayer2.testutil.FakeExtractorInput; 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 6d29af5127..567be685db 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 androidx.test.ext.junit.runners.AndroidJUnit4; 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 final class VorbisBitArrayTest { 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 9f0d6e0ff2..fb6892b364 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 com.google.android.exoplayer2.util.ParsableByteArray; 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 final class VorbisUtilTest { @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 final class VorbisUtilTest { @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 final class VorbisUtilTest { @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 4c31858a41..ea81846cee 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.io.IOException; 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 @@ import org.junit.runner.RunWith; * 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 1c28a143fa..3fa8d8a742 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.junit.runner.RunWith; 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 @@ import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; * AmrExtractorNonParameterizedTest}. */ @RunWith(ParameterizedRobolectricTestRunner.class) +@DoNotInstrument public final class AmrExtractorParameterizedTest { @Parameters(name = "{0}") @@ -71,7 +73,6 @@ public final class AmrExtractorParameterizedTest { 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 534cb2572f..e4ce7d2c97 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 java.util.Random; 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 16f92e2b4b..d89bcf4920 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.io.IOException; 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 1d776b9355..9a283928b8 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.junit.runner.RunWith; 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 e03b7ec6d6..cb1b04b9b9 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 java.util.List; 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 5a7e0a5a3e..f6e6b6f2a1 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.junit.runner.RunWith; 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 8e5556bf81..fa493f4452 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 com.google.common.collect.ImmutableList; 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 6c068d2587..5c9635095d 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.android.exoplayer2.util.MimeTypes; 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 a8275fd64c..3ba902ec88 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.Arrays; 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 class DefaultEbmlReaderTest { @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 class DefaultEbmlReaderTest { @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 class DefaultEbmlReaderTest { 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 64faff9a0e..28e7057577 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.junit.runner.RunWith; 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 7a3c73e4d5..860bc009b2 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.EOFException; 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 final class VarintReaderTest { @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 final class VarintReaderTest { 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 @@ public final class VarintReaderTest { 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 @@ public final class VarintReaderTest { 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 e3137a106d..713a269185 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 java.util.List; 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 24530c12f1..679ee526bc 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 java.util.List; 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 f209574de4..5d9e0380fb 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.junit.runner.RunWith; 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 7c481831c2..b18f32edb3 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 com.google.android.exoplayer2.util.Util; 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 final class XingSeekerTest { @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 final class XingSeekerTest { 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 651384094f..226b40559b 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 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.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 @@ public final class AtomParsersTest { 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 969c9b8d5a..a470457044 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.junit.runner.RunWith; 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 a9d2397ca7..14783a27b0 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.junit.runner.RunWith; 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 70e483457a..471e654a09 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 static com.google.common.truth.Truth.assertThat; 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 a270ee02a3..8d8bd0dfa1 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.junit.runner.RunWith; 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 final class Mp4ExtractorTest { 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 cc5dd3cdd1..e526c9e3c8 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 com.google.android.exoplayer2.util.ParsableByteArray; 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 final class PsshAtomUtilTest { 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 5b1c33303d..c22220931f 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.ArrayList; 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 e30f27713e..1ee87d1b1d 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.io.IOException; 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 d939d51b77..4131054775 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 com.google.android.exoplayer2.testutil.FakeExtractorOutput; 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 @@ import org.junit.runner.RunWith; * 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 8cbe254f07..48828b9b4a 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.junit.runner.RunWith; 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 @@ import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; *

    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 e74ecf7be0..d9bbe348f9 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.Arrays; 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 c952c0b220..89c8306342 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.io.IOException; 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 @@ public final class OggPageHeaderTest { 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 7db02d4789..e938743379 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 com.google.android.exoplayer2.util.ParsableByteArray; 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 final class VorbisReaderTest { 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 @@ public final class VorbisReaderTest { } } } - } 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 3856f2b573..5873bfc9b7 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 com.google.common.collect.ImmutableList; 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 8b0ffef80d..6f28ecde4a 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.junit.runner.RunWith; 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 39ab1bb534..50f04c43fc 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.junit.runner.RunWith; 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 2770d4ef66..59c5130050 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 java.util.Random; 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 420d8d589b..fb70fe603c 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.junit.runner.RunWith; 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 6869c0314c..ed1726e50b 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 java.util.Arrays; 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 8c1805c568..df79f0bba9 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 java.io.IOException; 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 d2d76d6695..9c8ee8687b 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 java.util.Random; 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 688cc318f1..7143ca0783 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.junit.runner.RunWith; 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 a023a32729..7866e67d47 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 java.util.List; 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 final class SectionReaderTest { 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 final class SectionReaderTest { @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 @@ public final class SectionReaderTest { 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 final class SectionReaderTest { 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 0e55d292b8..97c74e4292 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 java.io.IOException; 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 a796f3c994..1123e14a96 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 java.util.Random; 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 87215d45ee..f113efbfa5 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.junit.runner.RunWith; 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 4217a1528a..cc35344b2a 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 com.google.common.collect.ImmutableList; 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 b7eecc1ff8..d8b86e1832 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 d31f1ce6a2..6c94d1d444 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 11d68b1c08..617df277bf 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 @@ import javax.crypto.spec.SecretKeySpec; } @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 5382e5f6e3..25c0e8c0e6 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 final class DefaultHlsDataSourceFactory implements HlsDataSourceFactory { 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 81798aa676..77f301a241 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 final class DefaultHlsExtractorFactory implements HlsExtractorFactory { @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 final class DefaultHlsExtractorFactory implements HlsExtractorFactory { // 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 efc7377902..7c36d257b1 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } } - /** - * 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; return trackSelection; } - /** - * Resets the source. - */ + /** Resets the source. */ public void reset() { fatalError = null; } @@ -554,7 +544,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public Object getSelectionData() { return null; } - } private static final class EncryptionKeyChunk extends DataChunk { @@ -883,8 +878,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 7ec2f6c1f5..499797c51a 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 cf908145a0..ff2dcf0ba9 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 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist; /** 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 e6295cf82b..930d497e74 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.EnsuresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 66dd308e52..785e7f1d36 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 final class HlsMediaPeriod 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 final class HlsMediaPeriod 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 final class HlsMediaPeriod // 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 final class HlsMediaPeriod } @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 @@ public final class HlsMediaPeriod 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 @@ public final class HlsMediaPeriod .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 86383a52ce..4b225d7743 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 @@ public final class HlsMediaSource extends BaseMediaSource 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 @@ public final class HlsMediaSource extends BaseMediaSource } @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 53d9b0cd9e..a590607850 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.source.SampleStream; 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 6e16abc519..05f7a7f8cc 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 @@ package com.google.android.exoplayer2.source.hls; 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.MonotonicNonNull; 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 { +/* package */ final class HlsSampleStreamWrapper + implements Loader.Callback, + Loader.ReleaseCallback, + SequenceableLoader, + ExtractorOutput, + UpstreamFormatChangedListener { - /** - * A callback to be notified of events. - */ + /** A callback to be notified of events. */ public interface Callback extends SequenceableLoader.Callback { /** @@ -235,10 +238,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } @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 83d4c31924..54de6425e6 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 final class 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 832de00cf9..7a5771e208 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 final class WebvttExtractor implements Extractor { // 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 @@ public final class WebvttExtractor implements Extractor { 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 @@ public final class WebvttExtractor implements Extractor { 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 39462f3d06..e68ffcc7c9 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 android.net.Uri; 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 @@ import java.util.concurrent.Executor; */ 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 final class HlsDownloader extends SegmentDownloader { 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 9ad1cb5934..0558105100 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.Assertions; 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 final class 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 final class DefaultHlsPlaylistTracker 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 final class DefaultHlsPlaylistTracker } 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 @@ public final class DefaultHlsPlaylistTracker 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 final class DefaultHlsPlaylistTracker 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 final class DefaultHlsPlaylistTracker 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 @@ public final class DefaultHlsPlaylistTracker long elapsedRealtime = mediaPlaylistLoader.startLoading( mediaPlaylistLoadable, - this, + /* callback= */ this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(mediaPlaylistLoadable.type)); eventDispatcher.loadStarted( new LoadEventInfo( @@ -711,30 +716,31 @@ public final class DefaultHlsPlaylistTracker 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 @@ public final class DefaultHlsPlaylistTracker 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 72f6a361d7..2db9425a84 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 final class HlsMasterPlaylist extends HlsPlaylist { this.groupId = groupId; this.name = name; } - } /** All of the media playlist URLs referenced by the playlist. */ @@ -214,8 +213,8 @@ public final class HlsMasterPlaylist extends HlsPlaylist { 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 @@ public final class HlsMasterPlaylist extends HlsPlaylist { } 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 4149b5476a..c0f867dc76 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 @@ public final class HlsMediaPlaylist extends HlsPlaylist { @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 final class HlsMediaPlaylist extends HlsPlaylist { 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 final class HlsMediaPlaylist extends HlsPlaylist { * 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 final class HlsMediaPlaylist extends HlsPlaylist { * #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 final class HlsMediaPlaylist extends HlsPlaylist { 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 final class HlsMediaPlaylist extends HlsPlaylist { || (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 final class HlsMediaPlaylist extends HlsPlaylist { 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 9cec1cd33b..17d31d4ceb 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 @@ import java.util.List; /** 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 @@ public abstract class HlsPlaylist implements FilterableManifest { 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 d781357480..ce44211b31 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; 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 final class HlsPlaylistParser implements ParsingLoadable.ParserFMTP 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 @@ import java.util.HashMap; // 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 418b9c2ce6..8f171ef44e 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 94c5902cd3..f8c51b33f1 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @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 1f1cb79595..3e92c7ef85 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 @@ import java.util.TreeSet; 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 @@ import java.util.TreeSet; * 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 82d15e7a7c..3b591aaa9b 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 @@ import java.security.NoSuchAlgorithmException; case DIGEST: return getDigestAuthorizationHeaderValue(authUserInfo, uri, requestMethod); default: - throw new ParserException(new UnsupportedOperationException()); + throw ParserException.createForManifestWithUnsupportedFeature( + /* message= */ null, new UnsupportedOperationException()); } } @@ -136,7 +137,7 @@ import java.security.NoSuchAlgorithmException; 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 b2624a041c..0c4cff6446 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } private void onDescribeResponseReceived(RtspDescribeResponse response) { + RtspSessionTiming sessionTiming = RtspSessionTiming.DEFAULT; @Nullable String sessionRangeAttributeString = response.sessionDescription.attributes.get(SessionDescription.ATTR_RANGE); - - 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); + if (sessionRangeAttributeString != null) { + try { + sessionTiming = RtspSessionTiming.parseTiming(sessionRangeAttributeString); + } catch (ParserException e) { + sessionInfoListener.onSessionTimelineRequestFailed("SDP format error.", /* cause= */ e); + return; + } } + + 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 6b56b7b5ce..12c980a1a3 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 @@ import java.util.Map; */ /* 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 @@ import java.util.Map; 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 @@ import java.util.Map; * @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 @@ import java.util.Map; 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 @@ import java.util.Map; * 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 db72bc0637..14bcdfceb6 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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 b6799e8b67..89cbaeddb3 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 static com.google.android.exoplayer2.util.Assertions.checkNotNull; 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 final class RtspMediaSource extends BaseMediaSource { 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 final class RtspMediaSource extends BaseMediaSource { 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 d45af667dc..526f508953 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @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 a6636effee..c8ffff2574 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; return C.LENGTH_UNSET; } } catch (NumberFormatException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(line, e); } } @@ -386,7 +386,7 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; /* 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 @@ import java.util.regex.Pattern; 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 989303b461..6a3403c797 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 com.google.common.collect.ImmutableList; 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 7d56f1c580..ec15fa7556 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 @@ package com.google.android.exoplayer2.source.rtsp; /** 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 @@ package com.google.android.exoplayer2.source.rtsp; 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 73276d3446..6e2186f5db 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 @@ import java.util.regex.Pattern; 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 03d1698b8b..5f4cf51b4b 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 37c6f9ed49..3e6d34038e 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 @@ import com.google.common.collect.ImmutableList; /** * 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 @@ import com.google.common.collect.ImmutableList; 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 @@ import com.google.common.collect.ImmutableList; 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 770709b1b1..33df3d6d1e 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 @@ import java.util.HashMap; 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 cb47251b71..6d37b12c89 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; try { return sessionDescriptionBuilder.build(); } catch (IllegalArgumentException | IllegalStateException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, e); } } @@ -198,7 +201,7 @@ import java.util.regex.Pattern; try { sessionDescriptionBuilder.addMediaDescription(mediaDescriptionBuilder.build()); } catch (IllegalArgumentException | IllegalStateException e) { - throw new ParserException(e); + throw ParserException.createForMalformedManifest(/* message= */ null, e); } } @@ -206,7 +209,8 @@ import java.util.regex.Pattern; 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 @@ import java.util.regex.Pattern; 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 bd036d9f1c..c96a3ea725 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 @@ import java.util.concurrent.LinkedBlockingQueue; } @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 @@ import java.util.concurrent.LinkedBlockingQueue; } 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 95bf5027ca..44331f524b 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 static com.google.android.exoplayer2.util.Assertions.checkState; 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 @@ import java.net.SocketTimeoutException; } @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 fe393a9eb5..ec747fa1e2 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; // 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 ba520f841b..33ab218a53 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; // 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 ef1855c95b..e3b7bd51a7 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /* 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; // 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ int numBytesInData = data.bytesLeft(); - fragmentedSampleSizeBytes += writeStartCode(trackOutput); + fragmentedSampleSizeBytes += writeStartCode(); trackOutput.sampleData(data, numBytesInData); fragmentedSampleSizeBytes += numBytesInData; @@ -202,13 +202,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } } + 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /* 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 2b04c08711..4758494273 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 @@ import org.json.JSONObject; 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 0000000000..dfaaf01691 --- /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 5e5f3085ed..129871c584 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 @@ import org.junit.runner.RunWith; @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 final class RtspClientTest { } @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()); + } - AtomicBoolean sessionTimelineUpdateEventReceived = new AtomicBoolean(); + @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 onSessionTimelineUpdated( RtspSessionTiming timing, ImmutableList tracks) { - sessionTimelineUpdateEventReceived.set(!tracks.isEmpty()); + tracksInSession.set(tracks); } @Override public void onSessionTimelineRequestFailed( String message, @Nullable Throwable cause) {} }, - new PlaybackEventListener() { - @Override - public void onRtspSetupCompleted() {} - - @Override - public void onPlaybackStarted( - long startPositionUs, ImmutableList trackTimingList) {} - - @Override - public void onPlaybackError(RtspPlaybackException error) {} - }, + EMPTY_PLAYBACK_LISTENER, /* userAgent= */ "ExoPlayer:RtspClientTest", - /* uri= */ Uri.parse( - Util.formatInvariant("rtsp://localhost:%d/test", serverRtspPortNumber))); + 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 onSessionTimelineUpdated( + RtspSessionTiming timing, ImmutableList tracks) { + tracksInSession.set(tracks); + } + + @Override + 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 onSessionTimelineUpdated( + RtspSessionTiming timing, ImmutableList tracks) {} + + @Override + public void onSessionTimelineRequestFailed( + String message, @Nullable Throwable cause) { + failureCause.set(cause); + } + }, + EMPTY_PLAYBACK_LISTENER, + /* userAgent= */ "ExoPlayer:RtspClientTest", + 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 b8b8cbc5dd..9c642729c6 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 final class RtspHeadersTest { 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 final class RtspHeadersTest { .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 final class RtspHeadersTest { .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 0000000000..9072103958 --- /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 363533536e..7a24183084 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 class RtspMediaTrackTest { 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 cc2f4d24a3..7e559b31a9 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 final class RtspMessageChannelTest { new RtspHeaders.Builder() .add(RtspHeaders.CSEQ, "2") .add(RtspHeaders.PUBLIC, "OPTIONS") - .build(), - ""); + .build()); RtspResponse describeResponse = new RtspResponse( @@ -82,8 +81,7 @@ public final class RtspMessageChannelTest { 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 final class RtspMessageChannelTest { 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 c0611dddca..92463f3085 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 final class RtspMessageUtilTest { 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 final class RtspMessageUtilTest { 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 final class RtspMessageUtilTest { "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 final class RtspMessageUtilTest { 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 final class RtspMessageUtilTest { 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 final class RtspMessageUtilTest { 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 0000000000..e46737d3d7 --- /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 89c2853354..fe537fc720 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 @@ package com.google.android.exoplayer2.source.rtsp; 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.ServerSocket; 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 @@ public final class RtspServer implements Closeable { 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; + + case METHOD_SETUP: + sendResponse(responseProvider.getSetupResponse(request.uri, request.headers), cSeq); + break; + + case METHOD_PLAY: + sendResponse(responseProvider.getPlayResponse(), cSeq); + break; + + case METHOD_TEARDOWN: + sendResponse(responseProvider.getTearDownResponse(), cSeq); break; default: - sendErrorResponse(STATUS_METHOD_NOT_ALLOWED, cSeq); + sendResponse(RtspTestUtils.RTSP_ERROR_METHOD_NOT_ALLOWED, cSeq); } } - private void onOptionsRequestReceived(String cSeq) { - sendResponseWithCommonHeaders( - /* status= */ STATUS_OK, - /* cSeq= */ cSeq, - /* additionalHeaders= */ ImmutableMap.of(RtspHeaders.PUBLIC, PUBLIC_SUPPORTED_METHODS), - /* messageBody= */ ""); - } - - 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); - } - - private void sendErrorResponse(int status, String cSeq) { - sendResponseWithCommonHeaders( - status, cSeq, /* additionalHeaders= */ ImmutableMap.of(), /* messageBody= */ ""); - } - - 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 0000000000..ce0f0c232d --- /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 b35dc98608..dd3ad568b4 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.source.smoothstreaming.manifest.SsManifest. 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 class DefaultSsChunkSource implements SsChunkSource { 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 class DefaultSsChunkSource implements SsChunkSource { 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 class DefaultSsChunkSource implements SsChunkSource { ? 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 class DefaultSsChunkSource implements SsChunkSource { // 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 class DefaultSsChunkSource implements SsChunkSource { @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 @@ public class DefaultSsChunkSource implements SsChunkSource { 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 da2ffe9006..cab77cb072 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 final class SsMediaSource extends BaseMediaSource */ 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 @@ public final class SsMediaSource extends BaseMediaSource // 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 final class SsMediaSource extends BaseMediaSource } @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 @@ public final class SsMediaSource extends BaseMediaSource 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 @@ public final class SsMediaSource extends BaseMediaSource 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 @@ public final class SsMediaSource extends BaseMediaSource 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 b91bfc8f67..97e155b379 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 class SsManifest implements FilterableManifest { } } - /** - * 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 @@ public class SsManifest implements FilterableManifest { * @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 class SsManifest implements FilterableManifest { * @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 class SsManifest implements FilterableManifest { 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 05eb8acc0d..b26e2d41d8 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 class SsManifestParser implements ParsingLoadable.Parser { 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { * 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { // 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { return defaultValue; } } - } private static class SmoothStreamingMediaParser extends ElementParser { @@ -380,8 +372,10 @@ public class SsManifestParser implements ParsingLoadable.Parser { 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 class SsManifestParser implements ParsingLoadable.Parser { } } } - 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { // 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { } 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { } 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 class SsManifestParser implements ParsingLoadable.Parser { 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 class SsManifestParser implements ParsingLoadable.Parser { @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 class SsManifestParser implements ParsingLoadable.Parser { } 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 @@ public class SsManifestParser implements ParsingLoadable.Parser { @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 @@ public class SsManifestParser implements ParsingLoadable.Parser { } 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 998820de4b..416e4b92a6 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 @@ package com.google.android.exoplayer2.source.smoothstreaming.offline; 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 @@ import java.util.concurrent.Executor; */ 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 final class SsDownloader extends SegmentDownloader { 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 @@ public final class SsDownloader extends SegmentDownloader { } 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 1f28d2263b..7e6f659ce7 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 @@ package com.google.android.exoplayer2.source.smoothstreaming; 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 class SsMediaSourceTest { 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 e5a7ee5add..320db6bad2 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 final class SsManifestParserTest { 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 2e9710dc15..e400630d5e 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 @@ import java.nio.ByteBuffer; } 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 1ca5be3570..aa0437daba 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.RequiresApi; 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 final class Transformer { } @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 c5be7dc029..6198054aa2 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.C; 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 @@ import java.nio.ByteBuffer; 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 @@ import java.nio.ByteBuffer; .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 @@ import java.nio.ByteBuffer; 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 @@ import java.nio.ByteBuffer; 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 33888226b8..40d6690a30 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 a63db831fc..c29289e4c8 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 @@ public class SefSlowMotionVideoSampleTransformerTest { /** 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 @@ public class SefSlowMotionVideoSampleTransformerTest { * @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 @@ public class SefSlowMotionVideoSampleTransformerTest { * @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 f18183637b..2e6ea621db 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 cc0435be88..e2428948fa 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 @@ public final class AspectRatioFrameLayout extends FrameLayout { 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 @@ public final class AspectRatioFrameLayout extends FrameLayout { }) 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 @@ public final class AspectRatioFrameLayout extends FrameLayout { * 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 final class AspectRatioFrameLayout extends FrameLayout { 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 @@ public final class AspectRatioFrameLayout extends FrameLayout { 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 22c8ca78b1..dc96abb31d 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 final class 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 @@ public final class CaptionStyleCompat { 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 0000000000..629a8c0621 --- /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 ce041cba4e..2b0dce52d0 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 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * *

    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 class DefaultTimeBar extends View implements TimeBar { } // 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 class DefaultTimeBar extends View implements TimeBar { 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 class DefaultTimeBar extends View implements TimeBar { 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 class DefaultTimeBar extends View implements TimeBar { } @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 class DefaultTimeBar extends View implements TimeBar { 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 @@ public class DefaultTimeBar extends View implements TimeBar { 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 @@ public class DefaultTimeBar extends View implements TimeBar { 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 @@ public class DefaultTimeBar extends View implements TimeBar { } private void updateDrawableState() { - if (scrubberDrawable != null && scrubberDrawable.isStateful() + if (scrubberDrawable != null + && scrubberDrawable.isStateful() && scrubberDrawable.setState(getDrawableState())) { invalidate(); } @@ -944,7 +955,8 @@ public class DefaultTimeBar extends View implements TimeBar { 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 e4a88c083e..dd8a6d212f 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 android.widget.TextView; 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 @@ import java.util.concurrent.CopyOnWriteArrayList; * 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 @@ import java.util.concurrent.CopyOnWriteArrayList; *
  • 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 @@ import java.util.concurrent.CopyOnWriteArrayList; * 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 @@ import java.util.concurrent.CopyOnWriteArrayList; *
  • {@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 @@ import java.util.concurrent.CopyOnWriteArrayList; *

    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 class PlayerControlView extends FrameLayout { @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 class PlayerControlView extends FrameLayout { } @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 class PlayerControlView extends FrameLayout { 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 class PlayerControlView extends FrameLayout { 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 class PlayerControlView extends FrameLayout { } /** - * @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 class PlayerControlView extends FrameLayout { 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 @@ public class PlayerControlView extends FrameLayout { 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 @@ public class PlayerControlView extends FrameLayout { } 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 @@ public class PlayerControlView extends FrameLayout { 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 @@ public class PlayerControlView extends FrameLayout { } 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 class PlayerControlView extends FrameLayout { } } + @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 f59a211504..53d989d9d6 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 android.support.v4.media.session.MediaSessionCompat; 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 @@ import java.util.Map; *

    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 @@ import java.util.Map; *
  • 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 fastForwardIncrementMs} - Sets the fast forward increment. If set to zero the - * fast forward action is not used. + *
  • {@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 #setControlDispatcher(ControlDispatcher)} - *
    • Default: {@link DefaultControlDispatcher#DEFAULT_FAST_FORWARD_MS} (15000) + *
    • Corresponding setter: {@link #setUseRewindActionInCompactView(boolean)} + *
    • Default: {@code false} + *
    + *
  • {@code useFastForwardAction} - Sets whether the fast forward action is used. + *
      + *
    • 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 @@ import java.util.Map; *
    * * - *

    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 class PlayerNotificationManager { *

    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 class PlayerNotificationManager { *

    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 class PlayerNotificationManager { *

    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 class PlayerNotificationManager { *

    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 @@ public class PlayerNotificationManager { * * @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 class PlayerNotificationManager { 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 class PlayerNotificationManager { @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 class PlayerNotificationManager { 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 class PlayerNotificationManager { channelDescriptionResourceId, channelImportance); } + return new PlayerNotificationManager( context, channelId, @@ -630,18 +673,16 @@ public class PlayerNotificationManager { 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 class PlayerNotificationManager { 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 class PlayerNotificationManager { 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 @@ public class 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 @@ public class PlayerNotificationManager { usePreviousAction = true; useNextAction = true; usePlayPauseActions = true; + useRewindAction = true; + useFastForwardAction = true; colorized = true; useChronometer = true; color = Color.TRANSPARENT; @@ -917,25 +817,13 @@ public class PlayerNotificationManager { } /** - * @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 class PlayerNotificationManager { } } - /** - * @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 class PlayerNotificationManager { } } - /** - * 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 class PlayerNotificationManager { * 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 class PlayerNotificationManager { *

    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 @@ public class PlayerNotificationManager { * 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 @@ public class PlayerNotificationManager { stringActions.add(ACTION_PLAY); } } - if (enableFastForward) { + if (useFastForwardAction && enableFastForward) { stringActions.add(ACTION_FAST_FORWARD); } if (useNextAction && enableNext) { @@ -1474,14 +1371,19 @@ public class PlayerNotificationManager { 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 @@ public class PlayerNotificationManager { } 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 @@ public class PlayerNotificationManager { 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 class PlayerNotificationManager { 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 class PlayerNotificationManager { 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 c635418807..530b81e138 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.annotation.RequiresApi; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; *

    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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; */ 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 class PlayerView extends FrameLayout implements AdViewProvider { 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 class PlayerView extends FrameLayout implements AdViewProvider { 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 class PlayerView extends FrameLayout implements AdViewProvider { } 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 class PlayerView extends FrameLayout implements AdViewProvider { * @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 class PlayerView extends FrameLayout implements AdViewProvider { } /** - * @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 class PlayerView extends FrameLayout implements AdViewProvider { 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 class PlayerView extends FrameLayout implements AdViewProvider { *
  • {@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 @@ public class PlayerView extends FrameLayout implements AdViewProvider { 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 @@ public class PlayerView extends FrameLayout implements AdViewProvider { 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); } - return isArtworkSet; + + onContentAspectRatioChanged( + contentFrame, surfaceViewIgnoresVideoAspectRatio ? 0 : videoAspectRatio); + } + + @RequiresNonNull("artworkView") + private boolean setArtworkFromMediaMetadata(MediaMetadata mediaMetadata) { + if (mediaMetadata.artworkData == null) { + return false; + } + Bitmap bitmap = + BitmapFactory.decodeByteArray( + mediaMetadata.artworkData, /* offset= */ 0, mediaMetadata.artworkData.length); + return setDrawableArtwork(new BitmapDrawable(getResources(), bitmap)); } @RequiresNonNull("artworkView") @@ -1392,7 +1387,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider { 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 class PlayerView extends FrameLayout implements AdViewProvider { period = new Period(); } - // TextOutput implementation + // Player.Listener implementation @Override public void onCues(List cues) { @@ -1499,35 +1494,9 @@ public class PlayerView extends FrameLayout implements AdViewProvider { } } - // 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 class PlayerView extends FrameLayout implements AdViewProvider { } @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 class PlayerView extends FrameLayout implements AdViewProvider { 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 86086dd90b..8a4b6ae9a9 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.DefaultControlDispatcher; 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 @@ import java.util.concurrent.CopyOnWriteArrayList; * 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 @@ import java.util.concurrent.CopyOnWriteArrayList; *
  • 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 @@ import java.util.concurrent.CopyOnWriteArrayList; * 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 @@ import java.util.concurrent.CopyOnWriteArrayList; *
  • {@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 @@ import java.util.concurrent.CopyOnWriteArrayList; *

    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 class StyledPlayerControlView extends FrameLayout { @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 class StyledPlayerControlView extends FrameLayout { 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 class StyledPlayerControlView extends FrameLayout { } @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 class StyledPlayerControlView extends FrameLayout { @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 class StyledPlayerControlView extends FrameLayout { .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 class StyledPlayerControlView extends FrameLayout { 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 class StyledPlayerControlView extends FrameLayout { } /** - * @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 @@ public class StyledPlayerControlView extends FrameLayout { 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 @@ public class StyledPlayerControlView extends FrameLayout { } 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 @@ public class StyledPlayerControlView extends FrameLayout { } 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 @@ public class StyledPlayerControlView extends FrameLayout { } 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 @@ public class StyledPlayerControlView extends FrameLayout { 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,11 +1737,46 @@ public class StyledPlayerControlView extends FrameLayout { } private final class ComponentListener - implements Player.EventListener, + implements Player.Listener, TimeBar.OnScrubListener, OnClickListener, PopupWindow.OnDismissListener { + @Override + public void onEvents(Player player, Events events) { + if (events.containsAny(EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAY_WHEN_READY_CHANGED)) { + updatePlayPauseButton(); + } + if (events.containsAny( + EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_IS_PLAYING_CHANGED)) { + updateProgress(); + } + if (events.contains(EVENT_REPEAT_MODE_CHANGED)) { + updateRepeatModeButton(); + } + if (events.contains(EVENT_SHUFFLE_MODE_ENABLED_CHANGED)) { + updateShuffleButton(); + } + if (events.containsAny( + EVENT_REPEAT_MODE_CHANGED, + EVENT_SHUFFLE_MODE_ENABLED_CHANGED, + EVENT_POSITION_DISCONTINUITY, + EVENT_TIMELINE_CHANGED, + EVENT_SEEK_BACK_INCREMENT_CHANGED, + EVENT_SEEK_FORWARD_INCREMENT_CHANGED)) { + updateNavigation(); + } + if (events.containsAny(EVENT_POSITION_DISCONTINUITY, EVENT_TIMELINE_CHANGED)) { + updateTimeline(); + } + if (events.contains(EVENT_PLAYBACK_PARAMETERS_CHANGED)) { + updatePlaybackSpeedList(); + } + if (events.contains(EVENT_TRACKS_CHANGED)) { + updateTrackLists(); + } + } + @Override public void onScrubStart(TimeBar timeBar, long position) { scrubbing = true; @@ -1803,39 +1802,6 @@ public class StyledPlayerControlView extends FrameLayout { controlViewLayoutManager.resetHideCallbacks(); } - @Override - public void onEvents(Player player, Events events) { - if (events.containsAny(EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAY_WHEN_READY_CHANGED)) { - updatePlayPauseButton(); - } - if (events.containsAny( - EVENT_PLAYBACK_STATE_CHANGED, EVENT_PLAY_WHEN_READY_CHANGED, EVENT_IS_PLAYING_CHANGED)) { - updateProgress(); - } - if (events.contains(EVENT_REPEAT_MODE_CHANGED)) { - updateRepeatModeButton(); - } - if (events.contains(EVENT_SHUFFLE_MODE_ENABLED_CHANGED)) { - updateShuffleButton(); - } - if (events.containsAny( - EVENT_REPEAT_MODE_CHANGED, - EVENT_SHUFFLE_MODE_ENABLED_CHANGED, - EVENT_POSITION_DISCONTINUITY, - EVENT_TIMELINE_CHANGED)) { - updateNavigation(); - } - if (events.containsAny(EVENT_POSITION_DISCONTINUITY, EVENT_TIMELINE_CHANGED)) { - updateTimeline(); - } - if (events.contains(EVENT_PLAYBACK_PARAMETERS_CHANGED)) { - updatePlaybackSpeedList(); - } - if (events.contains(EVENT_TRACKS_CHANGED)) { - updateTrackLists(); - } - } - @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 6fbf759305..8c03272b3b 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 @@ import java.util.List; 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 e626a1c54f..b5a2822c8d 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.annotation.RequiresApi; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; *

    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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; */ 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 class StyledPlayerView extends FrameLayout implements AdViewProvider { 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 class StyledPlayerView extends FrameLayout implements AdViewProvider { 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 class StyledPlayerView extends FrameLayout implements AdViewProvider { } 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 class StyledPlayerView extends FrameLayout implements AdViewProvider { * @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 class StyledPlayerView extends FrameLayout implements AdViewProvider { } /** - * @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 class StyledPlayerView extends FrameLayout implements AdViewProvider { *
  • {@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 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { 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 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { } @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 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { 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 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { } } + 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 class StyledPlayerView extends FrameLayout implements AdViewProvider { period = new Period(); } - // TextOutput implementation + // Player.Listener implementation @Override public void onCues(List cues) { @@ -1518,35 +1535,9 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { } } - // 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 class StyledPlayerView extends FrameLayout implements AdViewProvider { } @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 class StyledPlayerView extends FrameLayout implements AdViewProvider { 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 5037eb4a4e..e21e0aa2dd 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 com.google.android.exoplayer2.util.Util; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; @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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } // 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; 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 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; // 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 5926b2dbde..9731506ecd 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 final class SubtitleView extends FrameLayout implements TextOutput { /** * 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 final class SubtitleView extends FrameLayout implements TextOutput { * * @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 @@ public final class SubtitleView extends FrameLayout implements TextOutput { } /** - * 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 final class SubtitleView extends FrameLayout implements TextOutput { } /** - * 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 final class SubtitleView extends FrameLayout implements TextOutput { } /** - * 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 @@ public final class SubtitleView extends FrameLayout implements TextOutput { } 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 9e3f2e42ff..467394f653 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 @@ public interface TimeBar { */ 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 be3fb9bc90..86bb242864 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 @@ public final class TrackSelectionDialogBuilder { } // 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 @@ public final class TrackSelectionDialogBuilder { .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 bb4806db06..6121aa1402 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 b8f7562969..0874d510e2 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 0000000000..4ebe0f42e5 --- /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 82ddfb4202..68469e8886 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 android.graphics.Color; 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 09efaad709..187dcf6204 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 com.google.android.exoplayer2.text.span.TextEmphasisSpan; 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 1ad530cc11..1b211626c3 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.TextAnnotation; 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 0f2c856dd7..8f2d9c6f21 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 c14295b027..418cb69176 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 @@ public final class DashDownloadTest { 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 c3e82ec33d..495372ab48 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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 final class DashStreamingTest { .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 @@ public final class DashStreamingTest { 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 4d888867f2..40037baba0 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 @@ import com.google.android.exoplayer2.util.Util; 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 @@ import com.google.android.exoplayer2.util.Util; // 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 @@ import com.google.android.exoplayer2.util.Util; 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 @@ import com.google.android.exoplayer2.util.Util; 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 @@ import com.google.android.exoplayer2.util.Util; // 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 @@ import com.google.android.exoplayer2.util.Util; // 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 @@ import com.google.android.exoplayer2.util.Util; 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 e43b2edb03..f023a73e9c 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 @@ import java.util.List; 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 @@ import java.util.List; 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 @@ import java.util.List; 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 @@ import java.util.List; * @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 @@ import java.util.List; 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 @@ import java.util.List; @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 @@ import java.util.List; 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 @@ import java.util.List; 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 @@ import java.util.List; 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 @@ import java.util.List; // 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 @@ import java.util.List; 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 @@ import java.util.List; private static boolean isFormatHandled(int formatSupport) { return RendererCapabilities.getFormatSupport(formatSupport) == C.FORMAT_HANDLED; } - } /** @@ -483,14 +510,12 @@ import java.util.List; @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 ce5ebfe303..9d962c281d 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 final class DashWidevineOfflineTest { "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 final class DashWidevineOfflineTest { 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 @@ public final class DashWidevineOfflineTest { 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 01b6ebb190..eb2341a74a 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 @@ import java.util.ArrayList; 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 @@ import java.util.ArrayList; 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 67a6a93357..efadf41737 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 ad24c61062..5148de832b 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 @@ import com.google.android.exoplayer2.util.Log; 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 d4bf0a0b83..05aac2fccc 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 @@ import android.app.Instrumentation; */ 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 918d2330f9..a58af6b55b 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.ExoPlayer; 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 @@ public class 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 @@ public class 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 class TestPlayerRunHelper { 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 class TestPlayerRunHelper { 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 class TestPlayerRunHelper { */ 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 class TestPlayerRunHelper { 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 class TestPlayerRunHelper { } }; 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 class TestPlayerRunHelper { } }; 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 class TestPlayerRunHelper { @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 class TestPlayerRunHelper { .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 946b5b78de..ee651f1908 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 bb201ef2ef..02c10855b5 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 bb201ef2ef..02c10855b5 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 80ac03b125..d9d6e116b6 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 80ac03b125..d9d6e116b6 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 80ac03b125..d9d6e116b6 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 80ac03b125..d9d6e116b6 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 bb201ef2ef..02c10855b5 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 7e398127fa..fc2adcadd7 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 bb201ef2ef..02c10855b5 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 bb201ef2ef..02c10855b5 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 bb201ef2ef..02c10855b5 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 df80dc226a..cd7232f583 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 bb201ef2ef..02c10855b5 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 0000000000..5fd303aed3 --- /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 0000000000..fa9e2af42e --- /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 0000000000..8b91ab1a5b --- /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 0000000000..22b236d572 --- /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 0000000000..5fd303aed3 --- /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 489763bbf8..8e996b6f31 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 a7ef1ecf4b..8e996b6f31 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 fffd040d68..f0fd81369f 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 a83a484f64..e67426081b 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 295fa07e94..605daaf8dd 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 8bf63a3901..605daaf8dd 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 b53c622489..dbc51ba77d 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 89899bb4e1..dbc51ba77d 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 7e7eb9ad0c..b9564a3ffc 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 2db85e42e0..b9564a3ffc 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 cc1c346b49..e96f346e29 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 c1b7f37bf3..f61ecb193a 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 4c0bb6d4ab..f61ecb193a 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 3bdb0839ae..417481edc3 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 0000000000..62d259b81b 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 188b2778a0..365416825c 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 0000000000..228e64a03b --- /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 0000000000..32207dde45 --- /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 0000000000..6b2e10a770 --- /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 0000000000..a7ee934a83 --- /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 0000000000..67ddc92635 --- /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 e149f16dfd..4a655512c2 100644 --- a/testdata/src/test/assets/media/ttml/rubies.xml +++ b/testdata/src/test/assets/media/ttml/rubies.xml @@ -7,6 +7,8 @@