From 16af5b7da612166824ccfaad035cde03954b81b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6rkem=20G=C3=BCcl=C3=BC?= Date: Fri, 18 Nov 2022 10:59:37 +0100 Subject: [PATCH 001/183] DashManifest has been enhanced to allow fetching Thumbnail Meta Data for a video position and with that allowing to display thumbnail images while seeking through a video. The demo app has beed enhanced to use this new API and display thumbnail images above the seek bar while scrubbing. --- demos/main/src/main/assets/media.exolist.json | 17 ++++ .../exoplayer2/demo/PlayerActivity.java | 4 + .../thumbnail/ThumbnailDescription.java | 60 ++++++++++++ .../source/dash/manifest/DashManifest.java | 92 +++++++++++++++++++ .../dash/manifest/DashManifestParser.java | 4 +- 5 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/thumbnail/ThumbnailDescription.java diff --git a/demos/main/src/main/assets/media.exolist.json b/demos/main/src/main/assets/media.exolist.json index ac7b5ce749..ce1528c19d 100644 --- a/demos/main/src/main/assets/media.exolist.json +++ b/demos/main/src/main/assets/media.exolist.json @@ -631,6 +631,23 @@ } ] }, + { + "name": "Thumbnails", + "samples": [ + { + "name": "Single adaptation set, 7 tiles at 10x1, each thumb 320x180", + "uri": "https://dash.akamaized.net/akamai/bbb_30fps/bbb_with_tiled_thumbnails.mpd" + }, + { + "name": "Single adaptation set, SegmentTemplate with SegmentTimeline", + "uri": "https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel-tiled-thumbnails-timeline.ism/.mpd" + }, + { + "name": "Single adaptation set, SegmentTemplate with SegmentNumber", + "uri": "https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel-tiled-thumbnails-numbered.ism/.mpd" + } + ] + }, { "name": "Misc", "samples": [ 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 8932b0780d..d7b381baf0 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 @@ -75,6 +75,7 @@ public class PlayerActivity extends AppCompatActivity protected LinearLayout debugRootView; protected TextView debugTextView; protected @Nullable ExoPlayer player; + DefaultThumbnailTimeBar timeBar; private boolean isShowingTrackSelectionDialog; private Button selectTracksButton; @@ -117,6 +118,8 @@ public class PlayerActivity extends AppCompatActivity playerView.setErrorMessageProvider(new PlayerErrorMessageProvider()); playerView.requestFocus(); + timeBar = playerView.findViewById(R.id.exo_progress); + if (savedInstanceState != null) { trackSelectionParameters = TrackSelectionParameters.fromBundle( @@ -282,6 +285,7 @@ public class PlayerActivity extends AppCompatActivity player.setPlayWhenReady(startAutoPlay); playerView.setPlayer(player); configurePlayerWithServerSideAdsLoader(); + timeBar.setThumbnailUtils(new DefaultThumbnailProvider(player, timeBar)); debugViewHelper = new DebugTextViewHelper(player, debugTextView); debugViewHelper.start(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/thumbnail/ThumbnailDescription.java b/library/core/src/main/java/com/google/android/exoplayer2/thumbnail/ThumbnailDescription.java new file mode 100644 index 0000000000..8984689404 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/thumbnail/ThumbnailDescription.java @@ -0,0 +1,60 @@ +package com.google.android.exoplayer2.thumbnail; + +import android.net.Uri; + +public class ThumbnailDescription { + + private final String id; + private final Uri uri; + private final int bitrate; + private final int rows; + private final int columns; + private final long startTimeMs; + private final long durationMs; + private final int imageWidth; // Image width (Pixel) + private final int imageHeight; // Image height (Pixel) + + public ThumbnailDescription(String id, Uri uri, int bitrate, int rows, int columns, long startTimeMs, long durationMs, int imageWidth, int imageHeight) { + this.id = id; + this.uri = uri; + this.bitrate = bitrate; + this.rows = rows; + this.columns = columns; + this.startTimeMs = startTimeMs; + this.durationMs = durationMs; + this.imageWidth = imageWidth; + this.imageHeight = imageHeight; + } + + public Uri getUri() { + return uri; + } + + public int getBitrate() { + return bitrate; + } + + public int getRows() { + return rows; + } + + public int getColumns() { + return columns; + } + + public long getStartTimeMs() { + return startTimeMs; + } + + public long getDurationMs() { + return durationMs; + } + + public int getImageWidth() { + return imageWidth; + } + + public int getImageHeight() { + return imageHeight; + } +} 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 6bdbb0d6b0..9123ea559c 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 @@ -15,12 +15,20 @@ */ package com.google.android.exoplayer2.source.dash.manifest; +import static com.google.android.exoplayer2.util.Util.castNonNull; + import android.net.Uri; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.offline.FilterableManifest; import com.google.android.exoplayer2.offline.StreamKey; +import com.google.android.exoplayer2.source.dash.BaseUrlExclusionList; +import com.google.android.exoplayer2.source.dash.DashSegmentIndex; +import com.google.android.exoplayer2.source.dash.DashUtil; +import com.google.android.exoplayer2.thumbnail.ThumbnailDescription; +import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.util.Util; +import com.google.common.base.Ascii; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; @@ -136,6 +144,90 @@ public class DashManifest implements FilterableManifest { return Util.msToUs(getPeriodDurationMs(index)); } + /** + * Returns a List of ThumbnailDescription for a given periodPosition, + * or null if no AdaptionSet of type C.TRACK_TYPE_IMAGE is available. + * @param periodPositionMs the period position to get ThumbnailDescription for, e.g. current player position. + * @return List of ThumbnailDescription from all Representations, or null if Thumbnails are not available in the DashManifest. + */ + @Nullable + public List getThumbnailDescriptions(long periodPositionMs) { + ArrayList thumbnailDescriptions = new ArrayList<>(); + + long periodPositionUs = Util.msToUs(periodPositionMs); + BaseUrlExclusionList baseUrlExclusionList = new BaseUrlExclusionList(); + + boolean isTrackTypeImageAvailable = false; + for (int i = 0; i < getPeriodCount(); i++) { + Period period = getPeriod(i); + long periodStartUs = Util.msToUs(period.startMs); + long periodDurationUs = getPeriodDurationUs(i); + + List adaptationSets = period.adaptationSets; + for (int j = 0; j < adaptationSets.size(); j++) { + AdaptationSet adaptationSet = adaptationSets.get(j); + if (adaptationSet.type != C.TRACK_TYPE_IMAGE) { + continue; + } + isTrackTypeImageAvailable = true; + + // thumbnails found + List representations = adaptationSet.representations; + for (int k = 0; k < representations.size(); k++) { + + Representation representation = representations.get(k); + DashSegmentIndex index = representation.getIndex(); + if (index == null) { + continue; + } + + String id = representation.format.id; + int bitrate = representation.format.bitrate; + int imageWidth = representation.format.width; + int imageHeight = representation.format.height; + + // get size XxY, e.g. 10x20, where 10 is column count and 20 is row count + int rows = 1; + int cols = 1; + for (int m = 0; m < representation.essentialProperties.size(); m++) { + Descriptor descriptor = representation.essentialProperties.get(m); + if ((Ascii.equalsIgnoreCase("http://dashif.org/thumbnail_tile", descriptor.schemeIdUri) || Ascii.equalsIgnoreCase("http://dashif.org/guidelines/thumbnail_tile", descriptor.schemeIdUri)) && descriptor.value != null) { + String size = descriptor.value; + String[] sizeSplit = size.split("x"); + if (sizeSplit.length != 2) { + continue; + } + cols = Integer.parseInt(sizeSplit[0]); + rows = Integer.parseInt(sizeSplit[1]); + } + } + + long now = Util.getNowUnixTimeMs(C.TIME_UNSET); + String baseUrl = castNonNull(baseUrlExclusionList.selectBaseUrl(representation.baseUrls)).url; + + // calculate the correct positionUs, which is FirstAvailableSegment.time + playerPosition, use that to get the correct segment + long firstSegmentNum = index.getFirstAvailableSegmentNum(periodDurationUs, Util.msToUs(now)); + long firstStartTimeUs = index.getTimeUs(firstSegmentNum); + long positionUs = firstStartTimeUs + periodPositionUs; + long segmentNumber = index.getSegmentNum(positionUs, periodDurationUs); + + long segmentStartTimeUs = periodStartUs + index.getTimeUs(segmentNumber); + long segmentDurationUs = index.getDurationUs(segmentNumber, periodDurationUs); + + RangedUri rangedUri = index.getSegmentUrl(segmentNumber); + DataSpec dataSpec = DashUtil.buildDataSpec(representation, baseUrl, rangedUri, /* flags= */ 0); + Uri uri = dataSpec.uri; + ThumbnailDescription thumbnailDescription = new ThumbnailDescription(id, uri, bitrate, rows, cols, Util.usToMs(segmentStartTimeUs - (dynamic ? firstStartTimeUs : 0)), Util.usToMs(segmentDurationUs), imageWidth, imageHeight); + thumbnailDescriptions.add(thumbnailDescription); + } + } + } + if (isTrackTypeImageAvailable) { + return thumbnailDescriptions; + } + return null; + } + @Override public final DashManifest copy(List streamKeys) { LinkedList keys = new LinkedList<>(streamKeys); 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 997e0e2ff7..919b1e253f 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 @@ -555,7 +555,9 @@ public class DashManifestParser extends DefaultHandler ? C.TRACK_TYPE_VIDEO : MimeTypes.BASE_TYPE_TEXT.equals(contentType) ? C.TRACK_TYPE_TEXT - : C.TRACK_TYPE_UNKNOWN; + : MimeTypes.BASE_TYPE_IMAGE.equals(contentType) + ? C.TRACK_TYPE_IMAGE + : C.TRACK_TYPE_UNKNOWN; } /** From 158cf0c8ed00d99244ded47acba5112c3b3fc96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6rkem=20G=C3=BCcl=C3=BC?= Date: Fri, 18 Nov 2022 12:49:34 +0100 Subject: [PATCH 002/183] Added missing files --- .../demo/DefaultThumbnailProvider.java | 194 ++++ .../demo/DefaultThumbnailTimeBar.java | 1026 +++++++++++++++++ .../exoplayer2/demo/ThumbnailProvider.java | 9 + .../layout/exo_styled_player_control_view.xml | 152 +++ 4 files changed, 1381 insertions(+) create mode 100644 demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailProvider.java create mode 100644 demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailTimeBar.java create mode 100644 demos/main/src/main/java/com/google/android/exoplayer2/demo/ThumbnailProvider.java create mode 100644 demos/main/src/main/res/layout/exo_styled_player_control_view.xml diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailProvider.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailProvider.java new file mode 100644 index 0000000000..c06144a1b8 --- /dev/null +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailProvider.java @@ -0,0 +1,194 @@ +package com.google.android.exoplayer2.demo; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.AsyncTask; +import android.util.LruCache; +import android.view.View; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.source.dash.manifest.DashManifest; +import com.google.android.exoplayer2.thumbnail.ThumbnailDescription; +import com.google.android.exoplayer2.util.Log; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.List; + +public class DefaultThumbnailProvider implements ThumbnailProvider { + + private static final String TAG_DEBUG = DefaultThumbnailProvider.class.getSimpleName(); + + private LruCache bitmapCache; + private View parent; + + //dummy bitmap to indicate that a download is already triggered but not finished yet + private final Bitmap dummyBitmap = Bitmap.createBitmap(1,1,Bitmap.Config.ARGB_8888); + @Nullable ExoPlayer exoPlayer; + + public DefaultThumbnailProvider(ExoPlayer exoPlayer, View view) { + this.exoPlayer = exoPlayer; + + this.parent = view; + + final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); + final int cacheSize = maxMemory / 4; + bitmapCache = new LruCache(cacheSize) { + @Override + protected int sizeOf(String key, Bitmap bitmap) { + return bitmap.getByteCount() / 1024; + } + }; + } + + public Bitmap getThumbnail(long position) { + return getThumbnail(position, true); + } + + private Bitmap getThumbnail(long position, boolean retrigger) { + if (exoPlayer != null) { + Object manifest = exoPlayer.getCurrentManifest(); + + ThumbnailDescription thumbnailDescription = null; + if (manifest instanceof DashManifest) { + DashManifest dashManifest = (DashManifest) manifest; + List thumbnailDescs = dashManifest.getThumbnailDescriptions(position); + //selected thumbnail description with lowest bitrate + for (ThumbnailDescription desc : thumbnailDescs) { + if (thumbnailDescription == null || thumbnailDescription.getBitrate() > desc.getBitrate()) { + thumbnailDescription = desc; + } + } + if (bitmapNotAvailableOrDownloadNotTriggeredYet(thumbnailDescription.getUri())) { + this.initThumbnailSource(thumbnailDescription); + return null; + } + } + + if (retrigger) { + //also download next and prev thumbnails to have a nicer UI user experience + getThumbnail(thumbnailDescription.getStartTimeMs() + thumbnailDescription.getDurationMs(), false); + getThumbnail(thumbnailDescription.getStartTimeMs() - thumbnailDescription.getDurationMs(), false); + } + + return getThumbnailInternal(position, thumbnailDescription); + } + return null; + } + + private boolean bitmapNotAvailableOrDownloadNotTriggeredYet(Uri uri) { + Bitmap tmp = bitmapCache.get(uri.toString()); + if (tmp != null) return false; + return true; + } + + private Bitmap getThumbnailInternal(long position, ThumbnailDescription thumbnailDescription) { + if (thumbnailDescription == null) return null; + + Bitmap thumbnailSource = bitmapCache.get(thumbnailDescription.getUri().toString()); + + if (thumbnailSource == null || thumbnailSource.getWidth() == 1) return null; + + if (position < thumbnailDescription.getStartTimeMs() || position > thumbnailDescription.getStartTimeMs() + thumbnailDescription.getDurationMs()) return null; + + int count = thumbnailDescription.getColumns() * thumbnailDescription.getRows(); + + int durationPerImage = (int)(thumbnailDescription.getDurationMs() / count); + + int imageNumberToUseWithinTile = (int)((position - thumbnailDescription.getStartTimeMs()) / durationPerImage); + + //handle special case if position == duration + if (imageNumberToUseWithinTile > count-1) imageNumberToUseWithinTile = count-1; + + int intRowToUse = (int)(imageNumberToUseWithinTile / thumbnailDescription.getColumns()); + + int intColToUse = imageNumberToUseWithinTile - intRowToUse * thumbnailDescription.getColumns(); + + double thumbnailWidth = (double) thumbnailDescription.getImageWidth() / thumbnailDescription.getColumns(); + double thumbnailHeight = (double) thumbnailDescription.getImageHeight() / thumbnailDescription.getRows(); + + int cropXLeft = (int)Math.round(intColToUse * thumbnailWidth); + int cropYTop = (int)Math.round(intRowToUse * thumbnailHeight); + + if (cropXLeft + thumbnailWidth <= thumbnailSource.getWidth() && cropYTop + thumbnailHeight <= thumbnailSource.getHeight()) { + return Bitmap.createBitmap(thumbnailSource + , cropXLeft, cropYTop, (int) thumbnailWidth, (int) thumbnailHeight); + } + else { + Log.d(TAG_DEBUG, "Image does not have expected (" + thumbnailDescription.getImageWidth() + "x" + thumbnailDescription.getImageHeight() + ") dimensions to crop. Source " + thumbnailDescription.getUri()); + return null; + } + } + + private synchronized void initThumbnailSource(ThumbnailDescription thumbnailDescription){ + String path = thumbnailDescription.getUri().toString(); + if (path == null) return; + + if (bitmapCache.get(path) != null) return; + bitmapCache.put(path, dummyBitmap); + + RetrieveThumbnailImageTask currentTask = new RetrieveThumbnailImageTask(); + currentTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, path); + } + + class RetrieveThumbnailImageTask extends AsyncTask { + + String downloadedUrl; + + RetrieveThumbnailImageTask() { + + } + + @Override + protected void onCancelled() { + super.onCancelled(); + if (downloadedUrl != null) bitmapCache.remove(downloadedUrl); + } + + protected Bitmap doInBackground(String... urls) { + downloadedUrl = urls[0]; + InputStream in =null; + Bitmap thumbnailToDownload=null; + int responseCode = -1; + + try{ + URL url = new URL(downloadedUrl); + if (!isCancelled()) { + HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection(); + httpURLConnection.setDoInput(true); + httpURLConnection.connect(); + responseCode = httpURLConnection.getResponseCode(); + if(responseCode == HttpURLConnection.HTTP_OK) + { + if (!isCancelled()) { + in = httpURLConnection.getInputStream(); + if (!isCancelled()) { + thumbnailToDownload = BitmapFactory.decodeStream(in); + } + in.close(); + } + } + } + + } + catch(Exception ex){ + bitmapCache.remove(downloadedUrl); + System.out.println(ex); + } + + return thumbnailToDownload; + } + + protected void onPostExecute(Bitmap downloadedThumbnail) { + if (downloadedThumbnail != null) { + bitmapCache.put(downloadedUrl, downloadedThumbnail); + if (parent != null) parent.invalidate(); + } + else { + bitmapCache.remove(downloadedUrl); + } + } + } + +} diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailTimeBar.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailTimeBar.java new file mode 100644 index 0000000000..a3e75923e5 --- /dev/null +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailTimeBar.java @@ -0,0 +1,1026 @@ +/* + * Copyright (C) 2017 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.demo; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.ui.TimeBar; +import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Util; +import java.util.Collections; +import java.util.Formatter; +import java.util.Locale; +import java.util.concurrent.CopyOnWriteArraySet; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + +/** + * A time bar that shows a current position, buffered position, duration and ad markers. + * + *

A DefaultTimeBar can be customized by setting attributes, as outlined below. + * + *

Attributes

+ * + * The following attributes can be set on a DefaultTimeBar when used in a layout XML file: + * + *
    + *
  • {@code bar_height} - Dimension for the height of the time bar. + *
      + *
    • Default: {@link #DEFAULT_BAR_HEIGHT_DP} + *
    + *
  • {@code touch_target_height} - Dimension for the height of the area in which touch + * interactions with the time bar are handled. If no height is specified, this also determines + * the height of the view. + *
      + *
    • Default: {@link #DEFAULT_TOUCH_TARGET_HEIGHT_DP} + *
    + *
  • {@code ad_marker_width} - Dimension for the width of any ad markers shown on the + * bar. Ad markers are superimposed on the time bar to show the times at which ads will play. + *
      + *
    • Default: {@link #DEFAULT_AD_MARKER_WIDTH_DP} + *
    + *
  • {@code scrubber_enabled_size} - Dimension for the diameter of the circular scrubber + * handle when scrubbing is enabled but not in progress. Set to zero if no scrubber handle + * should be shown. + *
      + *
    • Default: {@link #DEFAULT_SCRUBBER_ENABLED_SIZE_DP} + *
    + *
  • {@code scrubber_disabled_size} - Dimension for the diameter of the circular scrubber + * handle when scrubbing isn't enabled. Set to zero if no scrubber handle should be shown. + *
      + *
    • Default: {@link #DEFAULT_SCRUBBER_DISABLED_SIZE_DP} + *
    + *
  • {@code scrubber_dragged_size} - Dimension for the diameter of the circular scrubber + * handle when scrubbing is in progress. Set to zero if no scrubber handle should be shown. + *
      + *
    • Default: {@link #DEFAULT_SCRUBBER_DRAGGED_SIZE_DP} + *
    + *
  • {@code scrubber_drawable} - Optional reference to a drawable to draw for the + * scrubber handle. If set, this overrides the default behavior, which is to draw a circle for + * the scrubber handle. + *
  • {@code played_color} - Color for the portion of the time bar representing media + * before the current playback position. + *
      + *
    • Corresponding method: {@link #setPlayedColor(int)} + *
    • Default: {@link #DEFAULT_PLAYED_COLOR} + *
    + *
  • {@code scrubber_color} - Color for the scrubber handle. + *
      + *
    • Corresponding method: {@link #setScrubberColor(int)} + *
    • Default: {@link #DEFAULT_SCRUBBER_COLOR} + *
    + *
  • {@code buffered_color} - Color for the portion of the time bar after the current + * played position up to the current buffered position. + *
      + *
    • Corresponding method: {@link #setBufferedColor(int)} + *
    • Default: {@link #DEFAULT_BUFFERED_COLOR} + *
    + *
  • {@code unplayed_color} - Color for the portion of the time bar after the current + * buffered position. + *
      + *
    • Corresponding method: {@link #setUnplayedColor(int)} + *
    • Default: {@link #DEFAULT_UNPLAYED_COLOR} + *
    + *
  • {@code ad_marker_color} - Color for unplayed ad markers. + *
      + *
    • Corresponding method: {@link #setAdMarkerColor(int)} + *
    • Default: {@link #DEFAULT_AD_MARKER_COLOR} + *
    + *
  • {@code played_ad_marker_color} - Color for played ad markers. + *
      + *
    • Corresponding method: {@link #setPlayedAdMarkerColor(int)} + *
    • Default: {@link #DEFAULT_PLAYED_AD_MARKER_COLOR} + *
    + *
+ */ +public class DefaultThumbnailTimeBar extends View implements TimeBar { + + /** Default height for the time bar, in dp. */ + public static final int DEFAULT_BAR_HEIGHT_DP = 4; + /** Default height for the touch target, in dp. */ + public static final int DEFAULT_TOUCH_TARGET_HEIGHT_DP = 26; + /** Default width for ad markers, in dp. */ + public static final int DEFAULT_AD_MARKER_WIDTH_DP = 4; + /** Default diameter for the scrubber when enabled, in dp. */ + public static final int DEFAULT_SCRUBBER_ENABLED_SIZE_DP = 12; + /** Default diameter for the scrubber when disabled, in dp. */ + public static final int DEFAULT_SCRUBBER_DISABLED_SIZE_DP = 0; + /** Default diameter for the scrubber when dragged, in dp. */ + public static final int DEFAULT_SCRUBBER_DRAGGED_SIZE_DP = 16; + /** Default color for the played portion of the time bar. */ + public static final int DEFAULT_PLAYED_COLOR = 0xFFFFFFFF; + /** Default color for the unplayed portion of the time bar. */ + public static final int DEFAULT_UNPLAYED_COLOR = 0x33FFFFFF; + /** Default color for the buffered portion of the time bar. */ + public static final int DEFAULT_BUFFERED_COLOR = 0xCCFFFFFF; + /** Default color for the scrubber handle. */ + public static final int DEFAULT_SCRUBBER_COLOR = 0xFFFFFFFF; + /** Default color for ad markers. */ + public static final int DEFAULT_AD_MARKER_COLOR = 0xB2FFFF00; + /** Default color for played ad markers. */ + public static final int DEFAULT_PLAYED_AD_MARKER_COLOR = 0x33FFFF00; + + /** 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; + + /** 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; + /** The ratio by which times are reduced in fine scrub mode. */ + private static final int FINE_SCRUB_RATIO = 3; + /** + * The time after which the scrubbing listener is notified that scrubbing has stopped after + * performing an incremental scrub using key input. + */ + private static final long STOP_SCRUBBING_TIMEOUT_MS = 1000; + + private static final int DEFAULT_INCREMENT_COUNT = 20; + + private static final float SHOWN_SCRUBBER_SCALE = 1.0f; + private static final float HIDDEN_SCRUBBER_SCALE = 0.0f; + + /** + * The name of the Android SDK view that most closely resembles this custom view. Used as the + * class name for accessibility. + */ + private static final String ACCESSIBILITY_CLASS_NAME = "android.widget.SeekBar"; + + private final Rect seekBounds; + private final Rect progressBar; + private final Rect bufferedBar; + private final Rect scrubberBar; + private final Paint playedPaint; + private final Paint bufferedPaint; + private final Paint unplayedPaint; + private final Paint adMarkerPaint; + private final Paint playedAdMarkerPaint; + private final Paint scrubberPaint; + @Nullable private final Drawable scrubberDrawable; + private final int barHeight; + private final int touchTargetHeight; + private final int barGravity; + private final int adMarkerWidth; + private final int scrubberEnabledSize; + private final int scrubberDisabledSize; + private final int scrubberDraggedSize; + private final int scrubberPadding; + private final int fineScrubYThreshold; + private final StringBuilder formatBuilder; + private final Formatter formatter; + private final Runnable stopScrubbingRunnable; + private final CopyOnWriteArraySet listeners; + private final Point touchPosition; + private final float density; + + private int keyCountIncrement; + private long keyTimeIncrement; + private int lastCoarseScrubXPosition; + private @MonotonicNonNull Rect lastExclusionRectangle; + + private ValueAnimator scrubberScalingAnimator; + private float scrubberScale; + private boolean scrubberPaddingDisabled; + private boolean scrubbing; + private long scrubPosition; + private long duration; + private long position; + private long bufferedPosition; + private int adGroupCount; + @Nullable private long[] adGroupTimesMs; + @Nullable private boolean[] playedAdGroups; + + private ThumbnailProvider thumbnailUtils; + //TODO put in ressource file + int targetThumbnailHeightInDp = 80; + + public DefaultThumbnailTimeBar(Context context) { + this(context, null); + } + + public DefaultThumbnailTimeBar(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public DefaultThumbnailTimeBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, attrs); + } + + public DefaultThumbnailTimeBar( + Context context, + @Nullable AttributeSet attrs, + int defStyleAttr, + @Nullable AttributeSet timebarAttrs) { + this(context, attrs, defStyleAttr, timebarAttrs, 0); + } + + // Suppress warnings due to usage of View methods in the constructor. + @SuppressWarnings("nullness:method.invocation") + public DefaultThumbnailTimeBar( + Context context, + @Nullable AttributeSet attrs, + int defStyleAttr, + @Nullable AttributeSet timebarAttrs, + int defStyleRes) { + super(context, attrs, defStyleAttr); + seekBounds = new Rect(); + progressBar = new Rect(); + bufferedBar = new Rect(); + scrubberBar = new Rect(); + playedPaint = new Paint(); + bufferedPaint = new Paint(); + unplayedPaint = new Paint(); + adMarkerPaint = new Paint(); + playedAdMarkerPaint = new Paint(); + scrubberPaint = new Paint(); + scrubberPaint.setAntiAlias(true); + listeners = new CopyOnWriteArraySet<>(); + touchPosition = new Point(); + + // Calculate the dimensions and paints for drawn elements. + Resources res = context.getResources(); + DisplayMetrics displayMetrics = res.getDisplayMetrics(); + density = displayMetrics.density; + fineScrubYThreshold = dpToPx(density, FINE_SCRUB_Y_THRESHOLD_DP); + int defaultBarHeight = dpToPx(density, DEFAULT_BAR_HEIGHT_DP); + int defaultTouchTargetHeight = dpToPx(density, DEFAULT_TOUCH_TARGET_HEIGHT_DP); + int defaultAdMarkerWidth = dpToPx(density, DEFAULT_AD_MARKER_WIDTH_DP); + int defaultScrubberEnabledSize = dpToPx(density, DEFAULT_SCRUBBER_ENABLED_SIZE_DP); + int defaultScrubberDisabledSize = dpToPx(density, DEFAULT_SCRUBBER_DISABLED_SIZE_DP); + int defaultScrubberDraggedSize = dpToPx(density, DEFAULT_SCRUBBER_DRAGGED_SIZE_DP); + if (timebarAttrs != null) { + TypedArray a = + context + .getTheme() + .obtainStyledAttributes( + timebarAttrs, com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar, defStyleAttr, defStyleRes); + try { + scrubberDrawable = a.getDrawable(com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_scrubber_drawable); + if (scrubberDrawable != null) { + setDrawableLayoutDirection(scrubberDrawable); + defaultTouchTargetHeight = + Math.max(scrubberDrawable.getMinimumHeight(), defaultTouchTargetHeight); + } + barHeight = + a.getDimensionPixelSize(com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_bar_height, defaultBarHeight); + touchTargetHeight = + a.getDimensionPixelSize( + com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_touch_target_height, defaultTouchTargetHeight); + barGravity = a.getInt(com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_bar_gravity, BAR_GRAVITY_CENTER); + adMarkerWidth = + a.getDimensionPixelSize( + com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_ad_marker_width, defaultAdMarkerWidth); + scrubberEnabledSize = + a.getDimensionPixelSize( + com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_scrubber_enabled_size, defaultScrubberEnabledSize); + scrubberDisabledSize = + a.getDimensionPixelSize( + com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_scrubber_disabled_size, defaultScrubberDisabledSize); + scrubberDraggedSize = + a.getDimensionPixelSize( + com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_scrubber_dragged_size, defaultScrubberDraggedSize); + int playedColor = a.getInt(com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_played_color, DEFAULT_PLAYED_COLOR); + int scrubberColor = + a.getInt(com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_scrubber_color, DEFAULT_SCRUBBER_COLOR); + int bufferedColor = + a.getInt(com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_buffered_color, DEFAULT_BUFFERED_COLOR); + int unplayedColor = + a.getInt(com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_unplayed_color, DEFAULT_UNPLAYED_COLOR); + int adMarkerColor = + a.getInt(com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_ad_marker_color, DEFAULT_AD_MARKER_COLOR); + int playedAdMarkerColor = + a.getInt( + com.google.android.exoplayer2.ui.R.styleable.DefaultTimeBar_played_ad_marker_color, DEFAULT_PLAYED_AD_MARKER_COLOR); + playedPaint.setColor(playedColor); + scrubberPaint.setColor(scrubberColor); + bufferedPaint.setColor(bufferedColor); + unplayedPaint.setColor(unplayedColor); + adMarkerPaint.setColor(adMarkerColor); + playedAdMarkerPaint.setColor(playedAdMarkerColor); + } finally { + a.recycle(); + } + } else { + barHeight = defaultBarHeight; + touchTargetHeight = defaultTouchTargetHeight; + barGravity = BAR_GRAVITY_CENTER; + adMarkerWidth = defaultAdMarkerWidth; + scrubberEnabledSize = defaultScrubberEnabledSize; + scrubberDisabledSize = defaultScrubberDisabledSize; + scrubberDraggedSize = defaultScrubberDraggedSize; + playedPaint.setColor(DEFAULT_PLAYED_COLOR); + scrubberPaint.setColor(DEFAULT_SCRUBBER_COLOR); + bufferedPaint.setColor(DEFAULT_BUFFERED_COLOR); + unplayedPaint.setColor(DEFAULT_UNPLAYED_COLOR); + adMarkerPaint.setColor(DEFAULT_AD_MARKER_COLOR); + playedAdMarkerPaint.setColor(DEFAULT_PLAYED_AD_MARKER_COLOR); + scrubberDrawable = null; + } + formatBuilder = new StringBuilder(); + formatter = new Formatter(formatBuilder, Locale.getDefault()); + stopScrubbingRunnable = () -> stopScrubbing(/* canceled= */ false); + if (scrubberDrawable != null) { + scrubberPadding = (scrubberDrawable.getMinimumWidth() + 1) / 2; + } else { + scrubberPadding = + (Math.max(scrubberDisabledSize, Math.max(scrubberEnabledSize, scrubberDraggedSize)) + 1) + / 2; + } + scrubberScale = 1.0f; + scrubberScalingAnimator = new ValueAnimator(); + scrubberScalingAnimator.addUpdateListener( + animation -> { + scrubberScale = (float) animation.getAnimatedValue(); + invalidate(seekBounds); + }); + duration = C.TIME_UNSET; + keyTimeIncrement = C.TIME_UNSET; + keyCountIncrement = DEFAULT_INCREMENT_COUNT; + setFocusable(true); + if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { + setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + } + } + + public void setThumbnailUtils(ThumbnailProvider thumbnailUtils) { + this.thumbnailUtils = thumbnailUtils; + } + + /** Shows the scrubber handle. */ + public void showScrubber() { + if (scrubberScalingAnimator.isStarted()) { + scrubberScalingAnimator.cancel(); + } + scrubberPaddingDisabled = false; + scrubberScale = 1; + invalidate(seekBounds); + } + + /** + * Shows the scrubber handle with animation. + * + * @param showAnimationDurationMs The duration for scrubber showing animation. + */ + public void showScrubber(long showAnimationDurationMs) { + if (scrubberScalingAnimator.isStarted()) { + scrubberScalingAnimator.cancel(); + } + scrubberPaddingDisabled = false; + scrubberScalingAnimator.setFloatValues(scrubberScale, SHOWN_SCRUBBER_SCALE); + scrubberScalingAnimator.setDuration(showAnimationDurationMs); + scrubberScalingAnimator.start(); + } + + /** Hides the scrubber handle. */ + public void hideScrubber(boolean disableScrubberPadding) { + if (scrubberScalingAnimator.isStarted()) { + scrubberScalingAnimator.cancel(); + } + scrubberPaddingDisabled = disableScrubberPadding; + scrubberScale = 0; + invalidate(seekBounds); + } + + /** + * Hides the scrubber handle with animation. + * + * @param hideAnimationDurationMs The duration for scrubber hiding animation. + */ + public void hideScrubber(long hideAnimationDurationMs) { + if (scrubberScalingAnimator.isStarted()) { + scrubberScalingAnimator.cancel(); + } + scrubberScalingAnimator.setFloatValues(scrubberScale, HIDDEN_SCRUBBER_SCALE); + scrubberScalingAnimator.setDuration(hideAnimationDurationMs); + scrubberScalingAnimator.start(); + } + + /** + * Sets the color for the portion of the time bar representing media before the playback position. + * + * @param playedColor The color for the portion of the time bar representing media before the + * playback position. + */ + public void setPlayedColor(@ColorInt int playedColor) { + playedPaint.setColor(playedColor); + invalidate(seekBounds); + } + + /** + * Sets the color for the scrubber handle. + * + * @param scrubberColor The color for the scrubber handle. + */ + public void setScrubberColor(@ColorInt int scrubberColor) { + scrubberPaint.setColor(scrubberColor); + invalidate(seekBounds); + } + + /** + * Sets the color for the portion of the time bar after the current played position up to the + * current buffered position. + * + * @param bufferedColor The color for the portion of the time bar after the current played + * position up to the current buffered position. + */ + public void setBufferedColor(@ColorInt int bufferedColor) { + bufferedPaint.setColor(bufferedColor); + invalidate(seekBounds); + } + + /** + * Sets the color for the portion of the time bar after the current played position. + * + * @param unplayedColor The color for the portion of the time bar after the current played + * position. + */ + public void setUnplayedColor(@ColorInt int unplayedColor) { + unplayedPaint.setColor(unplayedColor); + invalidate(seekBounds); + } + + /** + * Sets the color for unplayed ad markers. + * + * @param adMarkerColor The color for unplayed ad markers. + */ + public void setAdMarkerColor(@ColorInt int adMarkerColor) { + adMarkerPaint.setColor(adMarkerColor); + invalidate(seekBounds); + } + + /** + * Sets the color for played ad markers. + * + * @param playedAdMarkerColor The color for played ad markers. + */ + public void setPlayedAdMarkerColor(@ColorInt int playedAdMarkerColor) { + playedAdMarkerPaint.setColor(playedAdMarkerColor); + invalidate(seekBounds); + } + + // TimeBar implementation. + + @Override + public void addListener(OnScrubListener listener) { + Assertions.checkNotNull(listener); + listeners.add(listener); + } + + @Override + public void removeListener(OnScrubListener listener) { + listeners.remove(listener); + } + + @Override + public void setKeyTimeIncrement(long time) { + Assertions.checkArgument(time > 0); + keyCountIncrement = C.INDEX_UNSET; + keyTimeIncrement = time; + } + + @Override + public void setKeyCountIncrement(int count) { + Assertions.checkArgument(count > 0); + keyCountIncrement = count; + keyTimeIncrement = C.TIME_UNSET; + } + + @Override + public void setPosition(long position) { + if (this.position == position) { + return; + } + this.position = position; + setContentDescription(getProgressText()); + update(); + } + + @Override + public void setBufferedPosition(long bufferedPosition) { + if (this.bufferedPosition == bufferedPosition) { + return; + } + this.bufferedPosition = bufferedPosition; + update(); + } + + @Override + public void setDuration(long duration) { + if (this.duration == duration) { + return; + } + this.duration = duration; + if (scrubbing && duration == C.TIME_UNSET) { + stopScrubbing(/* canceled= */ true); + } + update(); + } + + @Override + public long getPreferredUpdateDelay() { + int timeBarWidthDp = pxToDp(density, progressBar.width()); + return timeBarWidthDp == 0 || duration == 0 || duration == C.TIME_UNSET + ? Long.MAX_VALUE + : duration / timeBarWidthDp; + } + + @Override + 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; + update(); + } + + // View methods. + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (scrubbing && !enabled) { + stopScrubbing(/* canceled= */ true); + } + } + + @Override + public void onDraw(Canvas canvas) { + canvas.save(); + drawTimeBar(canvas); + drawPlayhead(canvas); + canvas.restore(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled() || duration <= 0) { + return false; + } + Point touchPosition = resolveRelativeTouchPosition(event); + int x = touchPosition.x; + int y = touchPosition.y; + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (isInSeekBar(x, y)) { + positionScrubber(x); + startScrubbing(getScrubberPosition()); + update(); + invalidate(); + return true; + } + break; + case MotionEvent.ACTION_MOVE: + if (scrubbing) { + if (y < fineScrubYThreshold) { + int relativeX = x - lastCoarseScrubXPosition; + positionScrubber(lastCoarseScrubXPosition + relativeX / FINE_SCRUB_RATIO); + } else { + lastCoarseScrubXPosition = x; + positionScrubber(x); + } + updateScrubbing(getScrubberPosition()); + update(); + invalidate(); + return true; + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (scrubbing) { + stopScrubbing(/* canceled= */ event.getAction() == MotionEvent.ACTION_CANCEL); + return true; + } + break; + default: + // Do nothing. + } + return false; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (isEnabled()) { + long positionIncrement = getPositionIncrement(); + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_LEFT: + positionIncrement = -positionIncrement; + // Fall through. + case KeyEvent.KEYCODE_DPAD_RIGHT: + if (scrubIncrementally(positionIncrement)) { + removeCallbacks(stopScrubbingRunnable); + postDelayed(stopScrubbingRunnable, STOP_SCRUBBING_TIMEOUT_MS); + return true; + } + break; + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_ENTER: + if (scrubbing) { + stopScrubbing(/* canceled= */ false); + return true; + } + break; + default: + // Do nothing. + } + } + return super.onKeyDown(keyCode, event); + } + + @Override + protected void onFocusChanged( + boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) { + super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); + if (scrubbing && !gainFocus) { + stopScrubbing(/* canceled= */ false); + } + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + updateDrawableState(); + } + + @Override + public void jumpDrawablesToCurrentState() { + super.jumpDrawablesToCurrentState(); + if (scrubberDrawable != null) { + scrubberDrawable.jumpToCurrentState(); + } + } + + @Override + 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); + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height); + updateDrawableState(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + int width = right - left; + int height = bottom - top; + int seekLeft = getPaddingLeft(); + int seekRight = width - getPaddingRight(); + int seekBoundsY; + int progressBarY; + int scrubberPadding = scrubberPaddingDisabled ? 0 : this.scrubberPadding; + if (barGravity == BAR_GRAVITY_BOTTOM) { + seekBoundsY = height - getPaddingBottom() - touchTargetHeight; + progressBarY = + height - getPaddingBottom() - barHeight - Math.max(scrubberPadding - (barHeight / 2), 0); + } else { + seekBoundsY = (height - touchTargetHeight) / 2; + progressBarY = (height - barHeight) / 2; + } + seekBounds.set(seekLeft, seekBoundsY, seekRight, seekBoundsY + touchTargetHeight); + progressBar.set( + seekBounds.left + scrubberPadding, + progressBarY, + seekBounds.right - scrubberPadding, + progressBarY + barHeight); + if (Util.SDK_INT >= 29) { + setSystemGestureExclusionRectsV29(width, height); + } + update(); + } + + @Override + public void onRtlPropertiesChanged(int layoutDirection) { + if (scrubberDrawable != null && setDrawableLayoutDirection(scrubberDrawable, layoutDirection)) { + invalidate(); + } + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SELECTED) { + event.getText().add(getProgressText()); + } + event.setClassName(ACCESSIBILITY_CLASS_NAME); + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(ACCESSIBILITY_CLASS_NAME); + info.setContentDescription(getProgressText()); + if (duration <= 0) { + return; + } + if (Util.SDK_INT >= 21) { + info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD); + } else { + info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); + } + } + + @Override + public boolean performAccessibilityAction(int action, @Nullable Bundle args) { + if (super.performAccessibilityAction(action, args)) { + return true; + } + if (duration <= 0) { + return false; + } + if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) { + if (scrubIncrementally(-getPositionIncrement())) { + stopScrubbing(/* canceled= */ false); + } + } else if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) { + if (scrubIncrementally(getPositionIncrement())) { + stopScrubbing(/* canceled= */ false); + } + } else { + return false; + } + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + return true; + } + + // Internal methods. + + private void startScrubbing(long scrubPosition) { + this.scrubPosition = scrubPosition; + scrubbing = true; + setPressed(true); + ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + for (OnScrubListener listener : listeners) { + listener.onScrubStart(this, scrubPosition); + } + } + + private void updateScrubbing(long scrubPosition) { + if (this.scrubPosition == scrubPosition) { + return; + } + this.scrubPosition = scrubPosition; + for (OnScrubListener listener : listeners) { + listener.onScrubMove(this, scrubPosition); + } + } + + private void stopScrubbing(boolean canceled) { + removeCallbacks(stopScrubbingRunnable); + scrubbing = false; + setPressed(false); + ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(false); + } + invalidate(); + for (OnScrubListener listener : listeners) { + listener.onScrubStop(this, scrubPosition, canceled); + } + } + + /** + * Incrementally scrubs the position by {@code positionChange}. + * + * @param positionChange The change in the scrubber position, in milliseconds. May be negative. + * @return Returns whether the scrubber position changed. + */ + private boolean scrubIncrementally(long positionChange) { + if (duration <= 0) { + return false; + } + long previousPosition = scrubbing ? scrubPosition : position; + long scrubPosition = Util.constrainValue(previousPosition + positionChange, 0, duration); + if (scrubPosition == previousPosition) { + return false; + } + if (!scrubbing) { + startScrubbing(scrubPosition); + } else { + updateScrubbing(scrubPosition); + } + update(); + return true; + } + + private void update() { + bufferedBar.set(progressBar); + scrubberBar.set(progressBar); + long newScrubberTime = scrubbing ? scrubPosition : position; + if (duration > 0) { + int bufferedPixelWidth = (int) ((progressBar.width() * bufferedPosition) / duration); + bufferedBar.right = Math.min(progressBar.left + bufferedPixelWidth, progressBar.right); + int scrubberPixelPosition = (int) ((progressBar.width() * newScrubberTime) / duration); + scrubberBar.right = Math.min(progressBar.left + scrubberPixelPosition, progressBar.right); + } else { + bufferedBar.right = progressBar.left; + scrubberBar.right = progressBar.left; + } + invalidate(seekBounds); + } + + private void positionScrubber(float xPosition) { + scrubberBar.right = Util.constrainValue((int) xPosition, progressBar.left, progressBar.right); + } + + private Point resolveRelativeTouchPosition(MotionEvent motionEvent) { + touchPosition.set((int) motionEvent.getX(), (int) motionEvent.getY()); + return touchPosition; + } + + private long getScrubberPosition() { + if (progressBar.width() <= 0 || duration == C.TIME_UNSET) { + return 0; + } + return (scrubberBar.width() * duration) / progressBar.width(); + } + + private boolean isInSeekBar(float x, float y) { + return seekBounds.contains((int) x, (int) y); + } + + private void drawTimeBar(Canvas canvas) { + int progressBarHeight = progressBar.height(); + int barTop = progressBar.centerY() - progressBarHeight / 2; + int barBottom = barTop + progressBarHeight; + if (duration <= 0) { + canvas.drawRect(progressBar.left, barTop, progressBar.right, barBottom, unplayedPaint); + return; + } + int bufferedLeft = bufferedBar.left; + int bufferedRight = bufferedBar.right; + int progressLeft = Math.max(Math.max(progressBar.left, bufferedRight), scrubberBar.right); + if (progressLeft < progressBar.right) { + canvas.drawRect(progressLeft, barTop, progressBar.right, barBottom, unplayedPaint); + } + bufferedLeft = Math.max(bufferedLeft, scrubberBar.right); + if (bufferedRight > bufferedLeft) { + canvas.drawRect(bufferedLeft, barTop, bufferedRight, barBottom, bufferedPaint); + } + if (scrubberBar.width() > 0) { + canvas.drawRect(scrubberBar.left, barTop, scrubberBar.right, barBottom, playedPaint); + } + if (adGroupCount == 0) { + return; + } + long[] adGroupTimesMs = Assertions.checkNotNull(this.adGroupTimesMs); + boolean[] playedAdGroups = Assertions.checkNotNull(this.playedAdGroups); + int adMarkerOffset = adMarkerWidth / 2; + for (int i = 0; i < adGroupCount; i++) { + 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)); + Paint paint = playedAdGroups[i] ? playedAdMarkerPaint : adMarkerPaint; + canvas.drawRect(markerLeft, barTop, markerLeft + adMarkerWidth, barBottom, paint); + } + } + + private void drawPlayhead(Canvas canvas) { + if (duration <= 0) { + return; + } + 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 playheadRadius = (int) ((scrubberSize * scrubberScale) / 2); + canvas.drawCircle(playheadX, playheadY, playheadRadius, scrubberPaint); + + if (scrubbing) drawThumbnail(canvas, playheadRadius, playheadX, playheadY); + } else { + int scrubberDrawableWidth = (int) (scrubberDrawable.getIntrinsicWidth() * scrubberScale); + int scrubberDrawableHeight = (int) (scrubberDrawable.getIntrinsicHeight() * scrubberScale); + scrubberDrawable.setBounds( + playheadX - scrubberDrawableWidth / 2, + playheadY - scrubberDrawableHeight / 2, + playheadX + scrubberDrawableWidth / 2, + playheadY + scrubberDrawableHeight / 2); + scrubberDrawable.draw(canvas); + } + } + + private void drawThumbnail(Canvas canvas, int playheadRadius, int playheadX, int playheadY) { + + if (thumbnailUtils == null) return; + Bitmap b = thumbnailUtils.getThumbnail(getScrubberPosition()); + + if (b == null) return; + + //adapt thumbnail to desired UI size + double arFactor = (double) b.getWidth() / b.getHeight(); + b = Bitmap.createScaledBitmap(b, dpToPx((int)(targetThumbnailHeightInDp * arFactor)), dpToPx(targetThumbnailHeightInDp), false); + + int width = b.getWidth(); + int height = b.getHeight(); + int offset = (int)width / 2; + + int left = playheadX-offset; + + //handle full left, full right position cases + if (left < 0 ) left = 0; + if (left + width > progressBar.width() + playheadRadius) left = progressBar.width() + playheadRadius - width; + + canvas.drawBitmap(b, left, playheadY-playheadRadius*2-height, null); + } + + private int dpToPx(int dp){ + return (int) (dp * getContext().getResources().getDisplayMetrics().density); + } + + private void updateDrawableState() { + if (scrubberDrawable != null + && scrubberDrawable.isStateful() + && scrubberDrawable.setState(getDrawableState())) { + invalidate(); + } + } + + @RequiresApi(29) + private void setSystemGestureExclusionRectsV29(int width, int height) { + if (lastExclusionRectangle != null + && lastExclusionRectangle.width() == width + && lastExclusionRectangle.height() == height) { + // Allocating inside onLayout is considered a DrawAllocation lint error, so avoid if possible. + return; + } + lastExclusionRectangle = new Rect(/* left= */ 0, /* top= */ 0, width, height); + setSystemGestureExclusionRects(Collections.singletonList(lastExclusionRectangle)); + } + + private String getProgressText() { + return Util.getStringForTime(formatBuilder, formatter, position); + } + + private long getPositionIncrement() { + return keyTimeIncrement == C.TIME_UNSET + ? (duration == C.TIME_UNSET ? 0 : (duration / keyCountIncrement)) + : keyTimeIncrement; + } + + private boolean setDrawableLayoutDirection(Drawable drawable) { + return Util.SDK_INT >= 23 && setDrawableLayoutDirection(drawable, getLayoutDirection()); + } + + private static boolean setDrawableLayoutDirection(Drawable drawable, int layoutDirection) { + return Util.SDK_INT >= 23 && drawable.setLayoutDirection(layoutDirection); + } + + private static int dpToPx(float density, int dps) { + return (int) (dps * density + 0.5f); + } + + private static int pxToDp(float density, int px) { + return (int) (px / density); + } +} diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/ThumbnailProvider.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/ThumbnailProvider.java new file mode 100644 index 0000000000..129fc84b16 --- /dev/null +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/ThumbnailProvider.java @@ -0,0 +1,9 @@ +package com.google.android.exoplayer2.demo; + +import android.graphics.Bitmap; + +public interface ThumbnailProvider { + + public Bitmap getThumbnail(long position); + +} diff --git a/demos/main/src/main/res/layout/exo_styled_player_control_view.xml b/demos/main/src/main/res/layout/exo_styled_player_control_view.xml new file mode 100644 index 0000000000..2a6ae481da --- /dev/null +++ b/demos/main/src/main/res/layout/exo_styled_player_control_view.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 89e4b8d049507efeb610f437429f25cf18df8f8b Mon Sep 17 00:00:00 2001 From: rohks Date: Thu, 24 Nov 2022 17:15:07 +0000 Subject: [PATCH 003/183] Use `ParsableBitArray` instead of `ParsableByteArray` To avoid complicated bit shifting and masking. Also makes the code more readable. PiperOrigin-RevId: 490749482 --- .../android/exoplayer2/audio/Ac3Util.java | 53 ++++++++++++------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java b/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java index 6a5bfd8559..2a2f86424f 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java @@ -149,16 +149,21 @@ public final class Ac3Util { */ public static Format parseAc3AnnexFFormat( ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData) { - int fscod = (data.readUnsignedByte() & 0xC0) >> 6; + ParsableBitArray dataBitArray = new ParsableBitArray(); + dataBitArray.reset(data); + + int fscod = dataBitArray.readBits(2); int sampleRate = SAMPLE_RATE_BY_FSCOD[fscod]; - int nextByte = data.readUnsignedByte(); - int channelCount = CHANNEL_COUNT_BY_ACMOD[(nextByte & 0x38) >> 3]; - if ((nextByte & 0x04) != 0) { // lfeon + dataBitArray.skipBits(8); // bsid, bsmod + int channelCount = CHANNEL_COUNT_BY_ACMOD[dataBitArray.readBits(3)]; // acmod + if (dataBitArray.readBits(1) != 0) { // lfeon channelCount++; } - // bit_rate_code - 5 bits. 2 bits from previous byte and 3 bits from next. - int halfFrmsizecod = ((nextByte & 0x03) << 3) | ((data.readUnsignedByte() & 0xE0) >> 5); + int halfFrmsizecod = dataBitArray.readBits(5); // bit_rate_code int constantBitrate = BITRATE_BY_HALF_FRMSIZECOD[halfFrmsizecod]; + // Update data position + dataBitArray.byteAlign(); + data.setPosition(dataBitArray.getBytePosition()); return new Format.Builder() .setId(trackId) .setSampleMimeType(MimeTypes.AUDIO_AC3) @@ -183,37 +188,45 @@ public final class Ac3Util { */ public static Format parseEAc3AnnexFFormat( ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData) { - // 13 bits for data_rate, 3 bits for num_ind_sub which are ignored. - int peakBitrate = - ((data.readUnsignedByte() & 0xFF) << 5) | ((data.readUnsignedByte() & 0xF8) >> 3); + ParsableBitArray dataBitArray = new ParsableBitArray(); + dataBitArray.reset(data); + + int peakBitrate = dataBitArray.readBits(13); // data_rate + dataBitArray.skipBits(3); // num_ind_sub // Read the first independent substream. - int fscod = (data.readUnsignedByte() & 0xC0) >> 6; + int fscod = dataBitArray.readBits(2); int sampleRate = SAMPLE_RATE_BY_FSCOD[fscod]; - int nextByte = data.readUnsignedByte(); - int channelCount = CHANNEL_COUNT_BY_ACMOD[(nextByte & 0x0E) >> 1]; - if ((nextByte & 0x01) != 0) { // lfeon + dataBitArray.skipBits(10); // bsid, reserved, asvc, bsmod + int channelCount = CHANNEL_COUNT_BY_ACMOD[dataBitArray.readBits(3)]; // acmod + if (dataBitArray.readBits(1) != 0) { // lfeon channelCount++; } // Read the first dependent substream. - nextByte = data.readUnsignedByte(); - int numDepSub = ((nextByte & 0x1E) >> 1); + dataBitArray.skipBits(3); // reserved + int numDepSub = dataBitArray.readBits(4); // num_dep_sub + dataBitArray.skipBits(1); // numDepSub > 0 ? LFE2 : reserved if (numDepSub > 0) { - int lowByteChanLoc = data.readUnsignedByte(); + dataBitArray.skipBytes(6); // other channel configurations // Read Lrs/Rrs pair // TODO: Read other channel configuration - if ((lowByteChanLoc & 0x02) != 0) { + if (dataBitArray.readBits(1) != 0) { channelCount += 2; } + dataBitArray.skipBits(1); // Lc/Rc pair } + String mimeType = MimeTypes.AUDIO_E_AC3; - if (data.bytesLeft() > 0) { - nextByte = data.readUnsignedByte(); - if ((nextByte & 0x01) != 0) { // flag_ec3_extension_type_a + if (dataBitArray.bitsLeft() > 7) { + dataBitArray.skipBits(7); // reserved + if (dataBitArray.readBits(1) != 0) { // flag_ec3_extension_type_a mimeType = MimeTypes.AUDIO_E_AC3_JOC; } } + // Update data position + dataBitArray.byteAlign(); + data.setPosition(dataBitArray.getBytePosition()); return new Format.Builder() .setId(trackId) .setSampleMimeType(mimeType) From fd40cd4a257d02ece0fde907dea58fbdf93929e6 Mon Sep 17 00:00:00 2001 From: samrobinson Date: Thu, 24 Nov 2022 18:11:15 +0000 Subject: [PATCH 004/183] Bump muxer watchdog abort timer default timeout to 10s. PiperOrigin-RevId: 490756055 --- .../com/google/android/exoplayer2/transformer/DefaultMuxer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultMuxer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultMuxer.java index 8e45bcf522..8e796d6ab9 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultMuxer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultMuxer.java @@ -28,7 +28,7 @@ public final class DefaultMuxer implements Muxer { public static final class Factory implements Muxer.Factory { /** The default value returned by {@link #getMaxDelayBetweenSamplesMs()}. */ - public static final long DEFAULT_MAX_DELAY_BETWEEN_SAMPLES_MS = 3000; + public static final long DEFAULT_MAX_DELAY_BETWEEN_SAMPLES_MS = 10_000; private final Muxer.Factory muxerFactory; From 67955e0ce331481bcb3fd94c9ffb9632f27eae6e Mon Sep 17 00:00:00 2001 From: rohks Date: Thu, 24 Nov 2022 18:14:44 +0000 Subject: [PATCH 005/183] Convert bitrates to bps before setting it Format expects the values of `averageBitrate` and `peakBitrate` in bps and the value fetched from AC3SpecificBox and EC3SpecificBox is in kbps. PiperOrigin-RevId: 490756581 --- .../java/com/google/android/exoplayer2/audio/Ac3Util.java | 4 ++-- .../src/test/assets/extractordumps/mp4/sample_ac3.mp4.0.dump | 4 ++-- .../src/test/assets/extractordumps/mp4/sample_ac3.mp4.1.dump | 4 ++-- .../src/test/assets/extractordumps/mp4/sample_ac3.mp4.2.dump | 4 ++-- .../src/test/assets/extractordumps/mp4/sample_ac3.mp4.3.dump | 4 ++-- .../extractordumps/mp4/sample_ac3.mp4.unknown_length.dump | 4 ++-- .../extractordumps/mp4/sample_ac3_fragmented.mp4.0.dump | 4 ++-- .../extractordumps/mp4/sample_ac3_fragmented.mp4.1.dump | 4 ++-- .../extractordumps/mp4/sample_ac3_fragmented.mp4.2.dump | 4 ++-- .../extractordumps/mp4/sample_ac3_fragmented.mp4.3.dump | 4 ++-- .../mp4/sample_ac3_fragmented.mp4.unknown_length.dump | 4 ++-- .../src/test/assets/extractordumps/mp4/sample_eac3.mp4.0.dump | 2 +- .../src/test/assets/extractordumps/mp4/sample_eac3.mp4.1.dump | 2 +- .../src/test/assets/extractordumps/mp4/sample_eac3.mp4.2.dump | 2 +- .../src/test/assets/extractordumps/mp4/sample_eac3.mp4.3.dump | 2 +- .../extractordumps/mp4/sample_eac3.mp4.unknown_length.dump | 2 +- .../extractordumps/mp4/sample_eac3_fragmented.mp4.0.dump | 2 +- .../extractordumps/mp4/sample_eac3_fragmented.mp4.1.dump | 2 +- .../extractordumps/mp4/sample_eac3_fragmented.mp4.2.dump | 2 +- .../extractordumps/mp4/sample_eac3_fragmented.mp4.3.dump | 2 +- .../mp4/sample_eac3_fragmented.mp4.unknown_length.dump | 2 +- .../test/assets/extractordumps/mp4/sample_eac3joc.mp4.0.dump | 2 +- .../test/assets/extractordumps/mp4/sample_eac3joc.mp4.1.dump | 2 +- .../test/assets/extractordumps/mp4/sample_eac3joc.mp4.2.dump | 2 +- .../test/assets/extractordumps/mp4/sample_eac3joc.mp4.3.dump | 2 +- .../extractordumps/mp4/sample_eac3joc.mp4.unknown_length.dump | 2 +- .../extractordumps/mp4/sample_eac3joc_fragmented.mp4.0.dump | 2 +- .../extractordumps/mp4/sample_eac3joc_fragmented.mp4.1.dump | 2 +- .../extractordumps/mp4/sample_eac3joc_fragmented.mp4.2.dump | 2 +- .../extractordumps/mp4/sample_eac3joc_fragmented.mp4.3.dump | 2 +- .../mp4/sample_eac3joc_fragmented.mp4.unknown_length.dump | 2 +- 31 files changed, 42 insertions(+), 42 deletions(-) diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java b/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java index 2a2f86424f..07f2f710c6 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java @@ -160,7 +160,7 @@ public final class Ac3Util { channelCount++; } int halfFrmsizecod = dataBitArray.readBits(5); // bit_rate_code - int constantBitrate = BITRATE_BY_HALF_FRMSIZECOD[halfFrmsizecod]; + int constantBitrate = BITRATE_BY_HALF_FRMSIZECOD[halfFrmsizecod] * 1000; // Update data position dataBitArray.byteAlign(); data.setPosition(dataBitArray.getBytePosition()); @@ -191,7 +191,7 @@ public final class Ac3Util { ParsableBitArray dataBitArray = new ParsableBitArray(); dataBitArray.reset(data); - int peakBitrate = dataBitArray.readBits(13); // data_rate + int peakBitrate = dataBitArray.readBits(13) * 1000; // data_rate dataBitArray.skipBits(3); // num_ind_sub // Read the first independent substream. diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.0.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.0.dump index 71eed666b7..97bfb758dc 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.0.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.0.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 13824 sample count = 9 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 maxInputSize = 1566 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.1.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.1.dump index a6fbd97784..9e9b211ed9 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.1.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.1.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 9216 sample count = 6 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 maxInputSize = 1566 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.2.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.2.dump index e02699e2de..4e872b3fd5 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.2.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.2.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 4608 sample count = 3 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 maxInputSize = 1566 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.3.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.3.dump index 4b7e17e7c9..138696f8a7 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.3.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.3.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 1536 sample count = 1 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 maxInputSize = 1566 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.unknown_length.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.unknown_length.dump index 71eed666b7..97bfb758dc 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3.mp4.unknown_length.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 13824 sample count = 9 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 maxInputSize = 1566 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.0.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.0.dump index 84217c2e01..448e79e1fd 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.0.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.0.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 13824 sample count = 9 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.1.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.1.dump index 1edd06253f..0f902e441a 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.1.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.1.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 10752 sample count = 7 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.2.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.2.dump index 01fd6af916..d747be40c5 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.2.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.2.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 6144 sample count = 4 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.3.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.3.dump index c303da0e15..76738dd5b3 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.3.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.3.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 1536 sample count = 1 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.unknown_length.dump b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.unknown_length.dump index 84217c2e01..448e79e1fd 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_ac3_fragmented.mp4.unknown_length.dump @@ -10,8 +10,8 @@ track 0: total output bytes = 13824 sample count = 9 format 0: - averageBitrate = 384 - peakBitrate = 384 + averageBitrate = 384000 + peakBitrate = 384000 id = 1 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.0.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.0.dump index aba5268ea2..a50ee9fecd 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.0.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.0.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 216000 sample count = 54 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 maxInputSize = 4030 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.1.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.1.dump index ac03cfd484..089c940439 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.1.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.1.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 144000 sample count = 36 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 maxInputSize = 4030 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.2.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.2.dump index 1a61f528ac..5d481314d5 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.2.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.2.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 72000 sample count = 18 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 maxInputSize = 4030 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.3.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.3.dump index 431599a9be..0242518866 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.3.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.3.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 4000 sample count = 1 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 maxInputSize = 4030 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.unknown_length.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.unknown_length.dump index aba5268ea2..a50ee9fecd 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3.mp4.unknown_length.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 216000 sample count = 54 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 maxInputSize = 4030 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.0.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.0.dump index 6da60d472a..734051bb2d 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.0.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.0.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 216000 sample count = 54 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.1.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.1.dump index 646dd35d91..027e7eb633 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.1.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.1.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 148000 sample count = 37 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.2.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.2.dump index a7ba576bf5..db94e2636e 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.2.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.2.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 76000 sample count = 19 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.3.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.3.dump index 280d6febc4..854d952ad8 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.3.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.3.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 4000 sample count = 1 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.unknown_length.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.unknown_length.dump index 6da60d472a..734051bb2d 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3_fragmented.mp4.unknown_length.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 216000 sample count = 54 format 0: - peakBitrate = 1000 + peakBitrate = 1000000 id = 1 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.0.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.0.dump index c98e27dc19..45a51b50ae 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.0.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.0.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 163840 sample count = 64 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc maxInputSize = 2590 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.1.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.1.dump index 9c9cee29df..4ad3e45f53 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.1.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.1.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 110080 sample count = 43 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc maxInputSize = 2590 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.2.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.2.dump index 85c07f6d2d..0c53717c22 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.2.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.2.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 56320 sample count = 22 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc maxInputSize = 2590 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.3.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.3.dump index 56387fb3c7..c8cd33b57b 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.3.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.3.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 2560 sample count = 1 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc maxInputSize = 2590 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.unknown_length.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.unknown_length.dump index c98e27dc19..45a51b50ae 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc.mp4.unknown_length.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 163840 sample count = 64 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc maxInputSize = 2590 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.0.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.0.dump index c73a6282e8..87930b0bfb 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.0.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.0.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 163840 sample count = 64 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.1.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.1.dump index 78b392053e..e1aa764cfb 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.1.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.1.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 110080 sample count = 43 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.2.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.2.dump index 2558363342..c9f083805f 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.2.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.2.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 56320 sample count = 22 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.3.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.3.dump index 084d2aa030..a3875f612d 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.3.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.3.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 2560 sample count = 1 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.unknown_length.dump b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.unknown_length.dump index c73a6282e8..87930b0bfb 100644 --- a/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/mp4/sample_eac3joc_fragmented.mp4.unknown_length.dump @@ -10,7 +10,7 @@ track 0: total output bytes = 163840 sample count = 64 format 0: - peakBitrate = 640 + peakBitrate = 640000 id = 1 sampleMimeType = audio/eac3-joc channelCount = 6 From 7fffe6571745a2f349d152e085783471764dfb25 Mon Sep 17 00:00:00 2001 From: kimvde Date: Fri, 25 Nov 2022 07:28:48 +0000 Subject: [PATCH 006/183] Add checkbox in demo to enable watchdog timer PiperOrigin-RevId: 490836952 --- .../transformerdemo/ConfigurationActivity.java | 6 ++++++ .../exoplayer2/transformerdemo/TransformerActivity.java | 7 +++++++ .../src/main/res/layout/configuration_activity.xml | 9 +++++++++ demos/transformer/src/main/res/values/strings.xml | 1 + 4 files changed, 23 insertions(+) diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java index 06d72f9200..0837c98f47 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java @@ -69,6 +69,7 @@ public final class ConfigurationActivity extends AppCompatActivity { public static final String TRIM_END_MS = "trim_end_ms"; public static final String ENABLE_FALLBACK = "enable_fallback"; public static final String ENABLE_DEBUG_PREVIEW = "enable_debug_preview"; + public static final String ABORT_SLOW_TRANSFORMATION = "abort_slow_transformation"; public static final String HDR_MODE = "hdr_mode"; public static final String DEMO_EFFECTS_SELECTIONS = "demo_effects_selections"; public static final String PERIODIC_VIGNETTE_CENTER_X = "periodic_vignette_center_x"; @@ -164,6 +165,7 @@ public final class ConfigurationActivity extends AppCompatActivity { private @MonotonicNonNull CheckBox trimCheckBox; private @MonotonicNonNull CheckBox enableFallbackCheckBox; private @MonotonicNonNull CheckBox enableDebugPreviewCheckBox; + private @MonotonicNonNull CheckBox abortSlowTransformationCheckBox; private @MonotonicNonNull Spinner hdrModeSpinner; private @MonotonicNonNull Button selectDemoEffectsButton; private boolean @MonotonicNonNull [] demoEffectsSelections; @@ -257,6 +259,8 @@ public final class ConfigurationActivity extends AppCompatActivity { enableFallbackCheckBox = findViewById(R.id.enable_fallback_checkbox); enableDebugPreviewCheckBox = findViewById(R.id.enable_debug_preview_checkbox); + abortSlowTransformationCheckBox = findViewById(R.id.abort_slow_transformation_checkbox); + ArrayAdapter hdrModeAdapter = new ArrayAdapter<>(/* context= */ this, R.layout.spinner_item); hdrModeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); @@ -319,6 +323,7 @@ public final class ConfigurationActivity extends AppCompatActivity { "trimCheckBox", "enableFallbackCheckBox", "enableDebugPreviewCheckBox", + "abortSlowTransformationCheckBox", "hdrModeSpinner", "demoEffectsSelections" }) @@ -357,6 +362,7 @@ public final class ConfigurationActivity extends AppCompatActivity { } bundle.putBoolean(ENABLE_FALLBACK, enableFallbackCheckBox.isChecked()); bundle.putBoolean(ENABLE_DEBUG_PREVIEW, enableDebugPreviewCheckBox.isChecked()); + bundle.putBoolean(ABORT_SLOW_TRANSFORMATION, abortSlowTransformationCheckBox.isChecked()); String selectedhdrMode = String.valueOf(hdrModeSpinner.getSelectedItem()); bundle.putInt(HDR_MODE, checkNotNull(HDR_MODE_DESCRIPTIONS.get(selectedhdrMode))); bundle.putBooleanArray(DEMO_EFFECTS_SELECTIONS, demoEffectsSelections); diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java index 8e854517a0..c780e6e3ac 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java @@ -49,6 +49,7 @@ import com.google.android.exoplayer2.effect.RgbFilter; import com.google.android.exoplayer2.effect.RgbMatrix; import com.google.android.exoplayer2.effect.SingleColorLut; import com.google.android.exoplayer2.transformer.DefaultEncoderFactory; +import com.google.android.exoplayer2.transformer.DefaultMuxer; import com.google.android.exoplayer2.transformer.ProgressHolder; import com.google.android.exoplayer2.transformer.TransformationException; import com.google.android.exoplayer2.transformer.TransformationRequest; @@ -285,7 +286,13 @@ public final class TransformerActivity extends AppCompatActivity { if (bundle.getBoolean(ConfigurationActivity.ENABLE_DEBUG_PREVIEW)) { transformerBuilder.setDebugViewProvider(new DemoDebugViewProvider()); } + + if (!bundle.getBoolean(ConfigurationActivity.ABORT_SLOW_TRANSFORMATION)) { + transformerBuilder.setMuxerFactory( + new DefaultMuxer.Factory(/* maxDelayBetweenSamplesMs= */ C.TIME_UNSET)); + } } + return transformerBuilder .addListener( new Transformer.Listener() { diff --git a/demos/transformer/src/main/res/layout/configuration_activity.xml b/demos/transformer/src/main/res/layout/configuration_activity.xml index f652bb8a5c..f78f57fee9 100644 --- a/demos/transformer/src/main/res/layout/configuration_activity.xml +++ b/demos/transformer/src/main/res/layout/configuration_activity.xml @@ -197,6 +197,15 @@ android:layout_gravity="end" android:checked="true"/> + + + + diff --git a/demos/transformer/src/main/res/values/strings.xml b/demos/transformer/src/main/res/values/strings.xml index 4ea1fe46a7..0e4fb6e739 100644 --- a/demos/transformer/src/main/res/values/strings.xml +++ b/demos/transformer/src/main/res/values/strings.xml @@ -29,6 +29,7 @@ Rotate video (degrees) Enable fallback Enable debug preview + Abort slow transformation Trim HDR mode Add demo effects From 7d62943bcd149eecce77cb44e4f867128ca374d3 Mon Sep 17 00:00:00 2001 From: tonihei Date: Fri, 25 Nov 2022 15:36:22 +0000 Subject: [PATCH 007/183] Remove flakiness from DefaultAnalyticsCollectorTest Our FakeClock generally makes sure that playback tests are fully deterministic. However, this fails if the test uses blocking waits with clock.onThreadBlocked and where relevant Handlers are created without using the clock. To fix the flakiness, we can make the following adjustments: - Use TestExoPlayerBuilder instead of legacy ExoPlayerTestRunner to avoid onThreadBlocked calls. This also makes the tests more readable. - Use clock to create Handler for FakeVideoRenderer and FakeAudioRenderer. Ideally, this should be passed through RenderersFactory, but it's too disruptive given this is a public API. - Use clock for MediaSourceList and MediaPeriodQueue update handler. PiperOrigin-RevId: 490907495 --- .../exoplayer2/ExoPlayerImplInternal.java | 2 +- .../android/exoplayer2/MediaPeriodQueue.java | 5 +- .../android/exoplayer2/MediaSourceList.java | 167 +++-- .../android/exoplayer2/ExoPlayerTest.java | 21 +- .../exoplayer2/MediaPeriodQueueTest.java | 9 +- .../exoplayer2/MediaSourceListTest.java | 2 +- .../DefaultAnalyticsCollectorTest.java | 667 +++++++++--------- .../robolectric/TestPlayerRunHelper.java | 24 + .../testutil/FakeAudioRenderer.java | 29 +- .../testutil/FakeVideoRenderer.java | 51 +- .../testutil/TestExoPlayerBuilder.java | 18 +- 11 files changed, 570 insertions(+), 425 deletions(-) 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 7680e6a0a5..440ed8f660 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 @@ -273,7 +273,7 @@ import java.util.concurrent.atomic.AtomicBoolean; deliverPendingMessageAtStartPositionRequired = true; - Handler eventHandler = new Handler(applicationLooper); + HandlerWrapper eventHandler = clock.createHandler(applicationLooper, /* callback= */ null); queue = new MediaPeriodQueue(analyticsCollector, eventHandler); mediaSourceList = new MediaSourceList(/* listener= */ this, analyticsCollector, eventHandler, playerId); 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 13cd603169..0651dd8bf8 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 @@ -30,6 +30,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelector; import com.google.android.exoplayer2.trackselection.TrackSelectorResult; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.common.collect.ImmutableList; /** @@ -69,7 +70,7 @@ import com.google.common.collect.ImmutableList; private final Timeline.Period period; private final Timeline.Window window; private final AnalyticsCollector analyticsCollector; - private final Handler analyticsCollectorHandler; + private final HandlerWrapper analyticsCollectorHandler; private long nextWindowSequenceNumber; private @RepeatMode int repeatMode; @@ -89,7 +90,7 @@ import com.google.common.collect.ImmutableList; * on. */ public MediaPeriodQueue( - AnalyticsCollector analyticsCollector, Handler analyticsCollectorHandler) { + AnalyticsCollector analyticsCollector, HandlerWrapper analyticsCollectorHandler) { this.analyticsCollector = analyticsCollector; this.analyticsCollectorHandler = analyticsCollectorHandler; period = new Timeline.Period(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaSourceList.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaSourceList.java index 389ae64b74..7c65a1540d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaSourceList.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaSourceList.java @@ -15,10 +15,12 @@ */ package com.google.android.exoplayer2; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static java.lang.Math.max; import static java.lang.Math.min; import android.os.Handler; +import android.util.Pair; import androidx.annotation.Nullable; import com.google.android.exoplayer2.analytics.AnalyticsCollector; import com.google.android.exoplayer2.analytics.PlayerId; @@ -36,6 +38,7 @@ import com.google.android.exoplayer2.source.ShuffleOrder.DefaultShuffleOrder; 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.HandlerWrapper; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Util; import java.io.IOException; @@ -47,6 +50,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import org.checkerframework.checker.nullness.compatqual.NullableType; /** * Concatenates multiple {@link MediaSource}s. The list of {@link MediaSource}s can be modified @@ -76,11 +80,10 @@ import java.util.Set; private final IdentityHashMap mediaSourceByMediaPeriod; private final Map mediaSourceByUid; private final MediaSourceListInfoRefreshListener mediaSourceListInfoListener; - private final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher; - private final DrmSessionEventListener.EventDispatcher drmEventDispatcher; private final HashMap childSources; private final Set enabledMediaSourceHolders; - + private final AnalyticsCollector eventListener; + private final HandlerWrapper eventHandler; private ShuffleOrder shuffleOrder; private boolean isPrepared; @@ -100,7 +103,7 @@ import java.util.Set; public MediaSourceList( MediaSourceListInfoRefreshListener listener, AnalyticsCollector analyticsCollector, - Handler analyticsCollectorHandler, + HandlerWrapper analyticsCollectorHandler, PlayerId playerId) { this.playerId = playerId; mediaSourceListInfoListener = listener; @@ -108,12 +111,10 @@ import java.util.Set; mediaSourceByMediaPeriod = new IdentityHashMap<>(); mediaSourceByUid = new HashMap<>(); mediaSourceHolders = new ArrayList<>(); - mediaSourceEventDispatcher = new MediaSourceEventListener.EventDispatcher(); - drmEventDispatcher = new DrmSessionEventListener.EventDispatcher(); + eventListener = analyticsCollector; + eventHandler = analyticsCollectorHandler; childSources = new HashMap<>(); enabledMediaSourceHolders = new HashSet<>(); - mediaSourceEventDispatcher.addEventListener(analyticsCollectorHandler, analyticsCollector); - drmEventDispatcher.addEventListener(analyticsCollectorHandler, analyticsCollector); } /** @@ -307,7 +308,7 @@ import java.util.Set; Object mediaSourceHolderUid = getMediaSourceHolderUid(id.periodUid); MediaSource.MediaPeriodId childMediaPeriodId = id.copyWithPeriodUid(getChildPeriodUid(id.periodUid)); - MediaSourceHolder holder = Assertions.checkNotNull(mediaSourceByUid.get(mediaSourceHolderUid)); + MediaSourceHolder holder = checkNotNull(mediaSourceByUid.get(mediaSourceHolderUid)); enableMediaSource(holder); holder.activeMediaPeriodIds.add(childMediaPeriodId); MediaPeriod mediaPeriod = @@ -323,8 +324,7 @@ import java.util.Set; * @param mediaPeriod The period to release. */ public void releasePeriod(MediaPeriod mediaPeriod) { - MediaSourceHolder holder = - Assertions.checkNotNull(mediaSourceByMediaPeriod.remove(mediaPeriod)); + MediaSourceHolder holder = checkNotNull(mediaSourceByMediaPeriod.remove(mediaPeriod)); holder.mediaSource.releasePeriod(mediaPeriod); holder.activeMediaPeriodIds.remove(((MaskingMediaPeriod) mediaPeriod).id); if (!mediaSourceByMediaPeriod.isEmpty()) { @@ -449,8 +449,7 @@ import java.util.Set; private void maybeReleaseChildSource(MediaSourceHolder mediaSourceHolder) { // Release if the source has been removed from the playlist and no periods are still active. if (mediaSourceHolder.isRemoved && mediaSourceHolder.activeMediaPeriodIds.isEmpty()) { - MediaSourceAndListener removedChild = - Assertions.checkNotNull(childSources.remove(mediaSourceHolder)); + MediaSourceAndListener removedChild = checkNotNull(childSources.remove(mediaSourceHolder)); removedChild.mediaSource.releaseSource(removedChild.caller); removedChild.mediaSource.removeEventListener(removedChild.eventListener); removedChild.mediaSource.removeDrmEventListener(removedChild.eventListener); @@ -525,12 +524,8 @@ import java.util.Set; implements MediaSourceEventListener, DrmSessionEventListener { private final MediaSourceList.MediaSourceHolder id; - private MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher; - private DrmSessionEventListener.EventDispatcher drmEventDispatcher; public ForwardingEventListener(MediaSourceList.MediaSourceHolder id) { - mediaSourceEventDispatcher = MediaSourceList.this.mediaSourceEventDispatcher; - drmEventDispatcher = MediaSourceList.this.drmEventDispatcher; this.id = id; } @@ -542,8 +537,14 @@ import java.util.Set; @Nullable MediaSource.MediaPeriodId mediaPeriodId, LoadEventInfo loadEventData, MediaLoadData mediaLoadData) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - mediaSourceEventDispatcher.loadStarted(loadEventData, mediaLoadData); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> + eventListener.onLoadStarted( + eventParameters.first, eventParameters.second, loadEventData, mediaLoadData)); } } @@ -553,8 +554,14 @@ import java.util.Set; @Nullable MediaSource.MediaPeriodId mediaPeriodId, LoadEventInfo loadEventData, MediaLoadData mediaLoadData) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - mediaSourceEventDispatcher.loadCompleted(loadEventData, mediaLoadData); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> + eventListener.onLoadCompleted( + eventParameters.first, eventParameters.second, loadEventData, mediaLoadData)); } } @@ -564,8 +571,14 @@ import java.util.Set; @Nullable MediaSource.MediaPeriodId mediaPeriodId, LoadEventInfo loadEventData, MediaLoadData mediaLoadData) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - mediaSourceEventDispatcher.loadCanceled(loadEventData, mediaLoadData); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> + eventListener.onLoadCanceled( + eventParameters.first, eventParameters.second, loadEventData, mediaLoadData)); } } @@ -577,8 +590,19 @@ import java.util.Set; MediaLoadData mediaLoadData, IOException error, boolean wasCanceled) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - mediaSourceEventDispatcher.loadError(loadEventData, mediaLoadData, error, wasCanceled); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> + eventListener.onLoadError( + eventParameters.first, + eventParameters.second, + loadEventData, + mediaLoadData, + error, + wasCanceled)); } } @@ -587,8 +611,14 @@ import java.util.Set; int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - mediaSourceEventDispatcher.upstreamDiscarded(mediaLoadData); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> + eventListener.onUpstreamDiscarded( + eventParameters.first, checkNotNull(eventParameters.second), mediaLoadData)); } } @@ -597,8 +627,14 @@ import java.util.Set; int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - mediaSourceEventDispatcher.downstreamFormatChanged(mediaLoadData); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> + eventListener.onDownstreamFormatChanged( + eventParameters.first, eventParameters.second, mediaLoadData)); } } @@ -609,75 +645,94 @@ import java.util.Set; int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId, @DrmSession.State int state) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - drmEventDispatcher.drmSessionAcquired(state); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> + eventListener.onDrmSessionAcquired( + eventParameters.first, eventParameters.second, state)); } } @Override public void onDrmKeysLoaded( int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - drmEventDispatcher.drmKeysLoaded(); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> eventListener.onDrmKeysLoaded(eventParameters.first, eventParameters.second)); } } @Override public void onDrmSessionManagerError( int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId, Exception error) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - drmEventDispatcher.drmSessionManagerError(error); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> + eventListener.onDrmSessionManagerError( + eventParameters.first, eventParameters.second, error)); } } @Override public void onDrmKeysRestored( int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - drmEventDispatcher.drmKeysRestored(); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> eventListener.onDrmKeysRestored(eventParameters.first, eventParameters.second)); } } @Override public void onDrmKeysRemoved( int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - drmEventDispatcher.drmKeysRemoved(); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> eventListener.onDrmKeysRemoved(eventParameters.first, eventParameters.second)); } } @Override public void onDrmSessionReleased( int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) { - if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { - drmEventDispatcher.drmSessionReleased(); + @Nullable + Pair eventParameters = + getEventParameters(windowIndex, mediaPeriodId); + if (eventParameters != null) { + eventHandler.post( + () -> + eventListener.onDrmSessionReleased(eventParameters.first, eventParameters.second)); } } - /** Updates the event dispatcher and returns whether the event should be dispatched. */ - private boolean maybeUpdateEventDispatcher( + /** Updates the event parameters and returns whether the event should be dispatched. */ + @Nullable + private Pair getEventParameters( int childWindowIndex, @Nullable MediaSource.MediaPeriodId childMediaPeriodId) { @Nullable MediaSource.MediaPeriodId mediaPeriodId = null; if (childMediaPeriodId != null) { mediaPeriodId = getMediaPeriodIdForChildMediaPeriodId(id, childMediaPeriodId); if (mediaPeriodId == null) { // Media period not found. Ignore event. - return false; + return null; } } int windowIndex = getWindowIndexForChildWindowIndex(id, childWindowIndex); - if (mediaSourceEventDispatcher.windowIndex != windowIndex - || !Util.areEqual(mediaSourceEventDispatcher.mediaPeriodId, mediaPeriodId)) { - mediaSourceEventDispatcher = - MediaSourceList.this.mediaSourceEventDispatcher.withParameters( - windowIndex, mediaPeriodId, /* mediaTimeOffsetMs= */ 0L); - } - if (drmEventDispatcher.windowIndex != windowIndex - || !Util.areEqual(drmEventDispatcher.mediaPeriodId, mediaPeriodId)) { - drmEventDispatcher = - MediaSourceList.this.drmEventDispatcher.withParameters(windowIndex, mediaPeriodId); - } - return true; + return Pair.create(windowIndex, mediaPeriodId); } } } 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 7166819224..b1fbf116d9 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 @@ -151,6 +151,7 @@ import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.MimeTypes; +import com.google.android.exoplayer2.util.SystemClock; import com.google.android.exoplayer2.util.Util; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; @@ -11887,7 +11888,11 @@ public final class ExoPlayerTest { new TestExoPlayerBuilder(context) .setRenderersFactory( (handler, videoListener, audioListener, textOutput, metadataOutput) -> { - videoRenderer.set(new FakeVideoRenderer(handler, videoListener)); + videoRenderer.set( + new FakeVideoRenderer( + SystemClock.DEFAULT.createHandler( + handler.getLooper(), /* callback= */ null), + videoListener)); return new Renderer[] {videoRenderer.get()}; }) .build(); @@ -12024,7 +12029,12 @@ public final class ExoPlayerTest { new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()) .setRenderersFactory( (handler, videoListener, audioListener, textOutput, metadataOutput) -> - new Renderer[] {new FakeVideoRenderer(handler, videoListener)}) + new Renderer[] { + new FakeVideoRenderer( + SystemClock.DEFAULT.createHandler( + handler.getLooper(), /* callback= */ null), + videoListener) + }) .build(); AnalyticsListener listener = mock(AnalyticsListener.class); player.addAnalyticsListener(listener); @@ -12049,7 +12059,12 @@ public final class ExoPlayerTest { new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()) .setRenderersFactory( (handler, videoListener, audioListener, textOutput, metadataOutput) -> - new Renderer[] {new FakeVideoRenderer(handler, videoListener)}) + new Renderer[] { + new FakeVideoRenderer( + SystemClock.DEFAULT.createHandler( + handler.getLooper(), /* callback= */ null), + videoListener) + }) .build(); Player.Listener listener = mock(Player.Listener.class); player.addListener(listener); 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 db0f15cf11..6e5a4bed85 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 @@ -25,7 +25,6 @@ import static org.mockito.Mockito.mock; import static org.robolectric.Shadows.shadowOf; import android.net.Uri; -import android.os.Handler; import android.os.Looper; import android.util.Pair; import androidx.test.core.app.ApplicationProvider; @@ -48,6 +47,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelector; import com.google.android.exoplayer2.trackselection.TrackSelectorResult; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.util.Clock; +import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.common.collect.ImmutableList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; @@ -91,13 +91,14 @@ public final class MediaPeriodQueueTest { analyticsCollector.setPlayer( new ExoPlayer.Builder(ApplicationProvider.getApplicationContext()).build(), Looper.getMainLooper()); - mediaPeriodQueue = - new MediaPeriodQueue(analyticsCollector, new Handler(Looper.getMainLooper())); + HandlerWrapper handler = + Clock.DEFAULT.createHandler(Looper.getMainLooper(), /* callback= */ null); + mediaPeriodQueue = new MediaPeriodQueue(analyticsCollector, handler); mediaSourceList = new MediaSourceList( mock(MediaSourceList.MediaSourceListInfoRefreshListener.class), analyticsCollector, - new Handler(Looper.getMainLooper()), + handler, PlayerId.UNSET); rendererCapabilities = new RendererCapabilities[0]; trackSelector = mock(TrackSelector.class); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/MediaSourceListTest.java b/library/core/src/test/java/com/google/android/exoplayer2/MediaSourceListTest.java index 58fdd77f9a..c678a439f6 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/MediaSourceListTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/MediaSourceListTest.java @@ -64,7 +64,7 @@ public class MediaSourceListTest { new MediaSourceList( mock(MediaSourceList.MediaSourceListInfoRefreshListener.class), analyticsCollector, - Util.createHandlerForCurrentOrMainLooper(), + Clock.DEFAULT.createHandler(Util.getCurrentOrMainLooper(), /* callback= */ null), PlayerId.UNSET); } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/analytics/DefaultAnalyticsCollectorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/analytics/DefaultAnalyticsCollectorTest.java index f62d75955d..4985169b6f 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/analytics/DefaultAnalyticsCollectorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/analytics/DefaultAnalyticsCollectorTest.java @@ -47,6 +47,12 @@ import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_VI import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_VIDEO_FRAME_PROCESSING_OFFSET; import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_VIDEO_INPUT_FORMAT_CHANGED; import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_VIDEO_SIZE_CHANGED; +import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.playUntilPosition; +import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilError; +import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilIsLoading; +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.runUntilTimelineChanged; import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM; import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample; import static com.google.common.truth.Truth.assertThat; @@ -63,6 +69,8 @@ import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static org.robolectric.shadows.ShadowLooper.idleMainLooper; +import static org.robolectric.shadows.ShadowLooper.runMainLooperToNextTask; import android.graphics.SurfaceTexture; import android.os.Looper; @@ -101,8 +109,6 @@ import com.google.android.exoplayer2.source.MediaLoadData; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.ads.AdPlaybackState; -import com.google.android.exoplayer2.testutil.ActionSchedule; -import com.google.android.exoplayer2.testutil.ActionSchedule.PlayerRunnable; import com.google.android.exoplayer2.testutil.ExoPlayerTestRunner; import com.google.android.exoplayer2.testutil.FakeAudioRenderer; import com.google.android.exoplayer2.testutil.FakeClock; @@ -116,6 +122,7 @@ import com.google.android.exoplayer2.testutil.TestExoPlayerBuilder; import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.ConditionVariable; +import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.VideoSize; @@ -132,14 +139,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; -import org.robolectric.shadows.ShadowLooper; /** Integration test for {@link DefaultAnalyticsCollector}. */ @RunWith(AndroidJUnit4.class) public final class DefaultAnalyticsCollectorTest { - private static final String TAG = "DefaultAnalyticsCollectorTest"; - // Deprecated event constants. private static final long EVENT_PLAYER_STATE_CHANGED = 1L << 63; private static final long EVENT_SEEK_STARTED = 1L << 62; @@ -167,7 +171,6 @@ public final class DefaultAnalyticsCollectorTest { private static final Format VIDEO_FORMAT_DRM_1 = ExoPlayerTestRunner.VIDEO_FORMAT.buildUpon().setDrmInitData(DRM_DATA_1).build(); - private static final int TIMEOUT_MS = 10_000; private static final Timeline SINGLE_PERIOD_TIMELINE = new FakeTimeline(); private static final EventWindowAndPeriodId WINDOW_0 = new EventWindowAndPeriodId(/* windowIndex= */ 0, /* mediaPeriodId= */ null); @@ -217,7 +220,14 @@ public final class DefaultAnalyticsCollectorTest { FakeMediaSource mediaSource = new FakeMediaSource( Timeline.EMPTY, ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.play(); + player.setMediaSource(mediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_ENDED); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) .containsExactly( @@ -236,7 +246,14 @@ public final class DefaultAnalyticsCollectorTest { SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.play(); + player.setMediaSource(mediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) @@ -247,7 +264,7 @@ public final class DefaultAnalyticsCollectorTest { period0 /* ENDED */) .inOrder(); assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) - .containsExactly(WINDOW_0 /* PLAYLIST_CHANGED */, period0 /* SOURCE_UPDATE */) + .containsExactly(WINDOW_0 /* PLAYLIST_CHANGED */, WINDOW_0 /* SOURCE_UPDATE */) .inOrder(); assertThat(listener.getEvents(EVENT_IS_LOADING_CHANGED)) .containsExactly(period0 /* started */, period0 /* stopped */) @@ -297,7 +314,14 @@ public final class DefaultAnalyticsCollectorTest { SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT)); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.play(); + player.setMediaSource(mediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) @@ -378,7 +402,14 @@ public final class DefaultAnalyticsCollectorTest { new ConcatenatingMediaSource( new FakeMediaSource(SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.VIDEO_FORMAT), new FakeMediaSource(SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.AUDIO_FORMAT)); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.play(); + player.setMediaSource(mediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) @@ -449,23 +480,23 @@ public final class DefaultAnalyticsCollectorTest { ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT), new FakeMediaSource(SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.AUDIO_FORMAT)); - ActionSchedule actionSchedule = - new ActionSchedule.Builder(TAG) - .pause() - // Wait until second period has fully loaded to assert loading events without flakiness. - .waitForIsLoading(true) - .waitForIsLoading(false) - .seek(/* mediaItemIndex= */ 1, /* positionMs= */ 0) - .play() - .build(); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource, actionSchedule); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.setMediaSource(mediaSource); + player.prepare(); + // Wait until second period has fully loaded to assert loading events. + runUntilIsLoading(player, /* expectedIsLoading= */ true); + runUntilIsLoading(player, /* expectedIsLoading= */ false); + player.seekTo(/* mediaItemIndex= */ 1, /* positionMs= */ 0); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) .containsExactly( - WINDOW_0 /* setPlayWhenReady=true */, WINDOW_0 /* BUFFERING */, - WINDOW_0 /* setPlayWhenReady=false */, period0 /* READY */, period1 /* BUFFERING */, period1 /* setPlayWhenReady=true */, @@ -542,23 +573,24 @@ public final class DefaultAnalyticsCollectorTest { SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT)); - long periodDurationMs = + long windowDurationMs = SINGLE_PERIOD_TIMELINE.getWindow(/* windowIndex= */ 0, new Window()).getDurationMs(); - ActionSchedule actionSchedule = - new ActionSchedule.Builder(TAG) - .pause() - .waitForPlaybackState(Player.STATE_READY) - .playUntilPosition(/* mediaItemIndex= */ 0, periodDurationMs) - .seekAndWait(/* positionMs= */ 0) - .play() - .build(); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource, actionSchedule); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.setMediaSource(mediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_READY); + playUntilPosition(player, /* mediaItemIndex= */ 0, windowDurationMs - 100); + player.seekTo(/* positionMs= */ 0); + runUntilPlaybackState(player, Player.STATE_READY); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) .containsExactly( - WINDOW_0 /* setPlayWhenReady=true */, - WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* BUFFERING */, period0 /* READY */, period0 /* setPlayWhenReady=true */, @@ -653,17 +685,19 @@ public final class DefaultAnalyticsCollectorTest { new FakeMediaSource(SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.VIDEO_FORMAT); MediaSource mediaSource2 = new FakeMediaSource(SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.VIDEO_FORMAT); - ActionSchedule actionSchedule = - new ActionSchedule.Builder(TAG) - .pause() - .waitForPlaybackState(Player.STATE_READY) - .setMediaSources(/* resetPosition= */ false, mediaSource2) - .waitForTimelineChanged() - // Wait until loading started to prevent flakiness caused by loading finishing too fast. - .waitForIsLoading(true) - .play() - .build(); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource1, actionSchedule); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.setMediaSource(mediaSource1); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_READY); + player.setMediaSource(mediaSource2, /* resetPosition= */ false); + runUntilTimelineChanged(player); + // Wait until loading started to assert loading events. + runUntilIsLoading(player, /* expectedIsLoading= */ true); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); // Populate all event ids with last timeline (after second prepare). populateEventIds(listener.lastReportedTimeline); @@ -676,9 +710,7 @@ public final class DefaultAnalyticsCollectorTest { /* windowSequenceNumber= */ 0)); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) .containsExactly( - WINDOW_0 /* setPlayWhenReady=true */, WINDOW_0 /* BUFFERING */, - WINDOW_0 /* setPlayWhenReady=false */, period0Seq0 /* READY */, WINDOW_0 /* BUFFERING */, period0Seq1 /* setPlayWhenReady=true */, @@ -688,9 +720,9 @@ public final class DefaultAnalyticsCollectorTest { assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) .containsExactly( WINDOW_0 /* PLAYLIST_CHANGE */, - period0Seq0 /* SOURCE_UPDATE */, + WINDOW_0 /* SOURCE_UPDATE */, WINDOW_0 /* PLAYLIST_CHANGE */, - period0Seq1 /* SOURCE_UPDATE */); + WINDOW_0 /* SOURCE_UPDATE */); assertThat(listener.getEvents(EVENT_POSITION_DISCONTINUITY)) .containsExactly(WINDOW_0 /* REMOVE */); assertThat(listener.getEvents(EVENT_IS_LOADING_CHANGED)) @@ -753,28 +785,31 @@ public final class DefaultAnalyticsCollectorTest { public void reprepareAfterError() throws Exception { MediaSource mediaSource = new FakeMediaSource(SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.VIDEO_FORMAT); - ActionSchedule actionSchedule = - new ActionSchedule.Builder(TAG) - .pause() - .waitForPlaybackState(Player.STATE_READY) - .throwPlaybackException( - ExoPlaybackException.createForSource( - new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED)) - .waitForPlaybackState(Player.STATE_IDLE) - .seek(/* positionMs= */ 0) - .prepare() - // Wait until loading started to assert loading events without flakiness. - .waitForIsLoading(true) - .play() - .waitForPlaybackState(Player.STATE_ENDED) - .build(); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource, actionSchedule); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.setMediaSource(mediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_READY); + player + .createMessage( + (message, payload) -> { + throw ExoPlaybackException.createForSource( + new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED); + }) + .send(); + runUntilError(player); + player.seekTo(/* positionMs= */ 0); + player.prepare(); + // Wait until loading started to assert loading events. + runUntilIsLoading(player, /* expectedIsLoading= */ true); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) .containsExactly( - WINDOW_0 /* setPlayWhenReady=true */, - WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* BUFFERING */, period0Seq0 /* READY */, period0Seq0 /* IDLE */, @@ -784,7 +819,7 @@ public final class DefaultAnalyticsCollectorTest { period0Seq0 /* ENDED */) .inOrder(); assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) - .containsExactly(WINDOW_0 /* prepared */, period0Seq0 /* prepared */); + .containsExactly(WINDOW_0 /* prepared */, WINDOW_0 /* prepared */); assertThat(listener.getEvents(EVENT_POSITION_DISCONTINUITY)).containsExactly(period0Seq0); assertThat(listener.getEvents(EVENT_SEEK_STARTED)).containsExactly(period0Seq0); assertThat(listener.getEvents(EVENT_SEEK_PROCESSED)).containsExactly(period0Seq0); @@ -835,36 +870,33 @@ public final class DefaultAnalyticsCollectorTest { new FakeMediaSource(SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.VIDEO_FORMAT); final ConcatenatingMediaSource concatenatedMediaSource = new ConcatenatingMediaSource(childMediaSource, childMediaSource); - long periodDurationMs = + long windowDurationMs = SINGLE_PERIOD_TIMELINE.getWindow(/* windowIndex= */ 0, new Window()).getDurationMs(); - ActionSchedule actionSchedule = - new ActionSchedule.Builder(TAG) - .pause() - .waitForPlaybackState(Player.STATE_READY) - // Ensure second period is already being read from. - .playUntilPosition(/* mediaItemIndex= */ 0, /* positionMs= */ periodDurationMs) - .executeRunnable( - () -> - concatenatedMediaSource.moveMediaSource( - /* currentIndex= */ 0, /* newIndex= */ 1)) - .waitForTimelineChanged() - .waitForPlaybackState(Player.STATE_READY) - .play() - .build(); - TestAnalyticsListener listener = runAnalyticsTest(concatenatedMediaSource, actionSchedule); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.setMediaSource(concatenatedMediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_READY); + // Ensure second period is already being read from. + playUntilPosition(player, /* mediaItemIndex= */ 0, /* positionMs= */ windowDurationMs - 100); + concatenatedMediaSource.moveMediaSource(/* currentIndex= */ 0, /* newIndex= */ 1); + runUntilTimelineChanged(player); + runUntilPlaybackState(player, Player.STATE_READY); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) .containsExactly( - WINDOW_0 /* setPlayWhenReady=true */, - WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* BUFFERING */, window0Period1Seq0 /* READY */, window0Period1Seq0 /* setPlayWhenReady=true */, window0Period1Seq0 /* setPlayWhenReady=false */, - period1Seq0 /* setPlayWhenReady=true */, period1Seq0 /* BUFFERING */, period1Seq0 /* READY */, + period1Seq0 /* setPlayWhenReady=true */, period1Seq0 /* ENDED */) .inOrder(); assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) @@ -926,20 +958,22 @@ public final class DefaultAnalyticsCollectorTest { public void playlistOperations() throws Exception { MediaSource fakeMediaSource = new FakeMediaSource(SINGLE_PERIOD_TIMELINE, ExoPlayerTestRunner.VIDEO_FORMAT); - ActionSchedule actionSchedule = - new ActionSchedule.Builder(TAG) - .pause() - .waitForPlaybackState(Player.STATE_READY) - .addMediaSources(fakeMediaSource) - // Wait until second period has fully loaded to assert loading events without flakiness. - .waitForIsLoading(true) - .waitForIsLoading(false) - .removeMediaItem(/* index= */ 0) - .waitForPlaybackState(Player.STATE_BUFFERING) - .waitForPlaybackState(Player.STATE_READY) - .play() - .build(); - TestAnalyticsListener listener = runAnalyticsTest(fakeMediaSource, actionSchedule); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.setMediaSource(fakeMediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_READY); + player.addMediaSource(fakeMediaSource); + // Wait until second period has fully loaded to assert loading events. + runUntilIsLoading(player, /* expectedIsLoading= */ true); + runUntilIsLoading(player, /* expectedIsLoading= */ false); + player.removeMediaItem(/* index= */ 0); + runUntilPlaybackState(player, Player.STATE_BUFFERING); + runUntilPlaybackState(player, Player.STATE_READY); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); // Populate event ids with second to last timeline that still contained both periods. populateEventIds(listener.reportedTimelines.get(listener.reportedTimelines.size() - 2)); @@ -953,8 +987,6 @@ public final class DefaultAnalyticsCollectorTest { /* windowSequenceNumber= */ 1)); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) .containsExactly( - WINDOW_0 /* setPlayWhenReady=true */, - WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* BUFFERING */, period0Seq0 /* READY */, period0Seq1 /* BUFFERING */, @@ -965,7 +997,7 @@ public final class DefaultAnalyticsCollectorTest { assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) .containsExactly( WINDOW_0 /* PLAYLIST_CHANGED */, - period0Seq0 /* SOURCE_UPDATE (first item) */, + WINDOW_0 /* SOURCE_UPDATE (first item) */, period0Seq0 /* PLAYLIST_CHANGED (add) */, period0Seq0 /* SOURCE_UPDATE (second item) */, period0Seq1 /* PLAYLIST_CHANGED (remove) */) @@ -1063,60 +1095,53 @@ public final class DefaultAnalyticsCollectorTest { } }, ExoPlayerTestRunner.VIDEO_FORMAT); - ActionSchedule actionSchedule = - new ActionSchedule.Builder(TAG) - .executeRunnable( - new PlayerRunnable() { - @Override - public void run(ExoPlayer player) { - player.addListener( - new Player.Listener() { - @Override - public void onPositionDiscontinuity( - Player.PositionInfo oldPosition, - Player.PositionInfo newPosition, - @Player.DiscontinuityReason int reason) { - if (!player.isPlayingAd() - && reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) { - // Finished playing ad. Marked as played. - adPlaybackState.set( - adPlaybackState - .get() - .withPlayedAd( - /* adGroupIndex= */ playedAdCount.getAndIncrement(), - /* adIndexInAdGroup= */ 0)); - fakeMediaSource.setNewSourceInfo( - new FakeTimeline( - new TimelineWindowDefinition( - /* periodCount= */ 1, - /* id= */ 0, - /* isSeekable= */ true, - /* isDynamic= */ false, - contentDurationsUs, - adPlaybackState.get())), - /* sendManifestLoadEvents= */ false); - } - } - }); - } - }) - .pause() - // Ensure everything is preloaded. - .waitForIsLoading(true) - .waitForIsLoading(false) - .waitForPlaybackState(Player.STATE_READY) - // Wait in each content part to ensure previously triggered events get a chance to be - // delivered. This prevents flakiness caused by playback progressing too fast. - .playUntilPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 3_000) - .waitForPendingPlayerCommands() - .playUntilPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 8_000) - .waitForPendingPlayerCommands() - .play() - .waitForPlaybackState(Player.STATE_ENDED) - // Wait for final timeline change that marks post-roll played. - .waitForTimelineChanged() - .build(); - TestAnalyticsListener listener = runAnalyticsTest(fakeMediaSource, actionSchedule); + ExoPlayer player = setupPlayer(); + player.addListener( + new Player.Listener() { + @Override + public void onPositionDiscontinuity( + Player.PositionInfo oldPosition, + Player.PositionInfo newPosition, + @Player.DiscontinuityReason int reason) { + if (!player.isPlayingAd() && reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) { + // Finished playing ad. Marked as played. + adPlaybackState.set( + adPlaybackState + .get() + .withPlayedAd( + /* adGroupIndex= */ playedAdCount.getAndIncrement(), + /* adIndexInAdGroup= */ 0)); + fakeMediaSource.setNewSourceInfo( + new FakeTimeline( + new TimelineWindowDefinition( + /* periodCount= */ 1, + /* id= */ 0, + /* isSeekable= */ true, + /* isDynamic= */ false, + contentDurationsUs, + adPlaybackState.get())), + /* sendManifestLoadEvents= */ false); + } + } + }); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.setMediaSource(fakeMediaSource); + player.prepare(); + // Ensure everything is preloaded. + runUntilIsLoading(player, /* expectedIsLoading= */ true); + runUntilIsLoading(player, /* expectedIsLoading= */ false); + runUntilPlaybackState(player, Player.STATE_READY); + // Wait in each content part to ensure previously triggered events get a chance to be delivered. + playUntilPosition(player, /* mediaItemIndex= */ 0, /* positionMs= */ 3_000); + runUntilPendingCommandsAreFullyHandled(player); + playUntilPosition(player, /* mediaItemIndex= */ 0, /* positionMs= */ 8_000); + runUntilPendingCommandsAreFullyHandled(player); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); + // Wait for final timeline change that marks post-roll played. + runUntilTimelineChanged(player); Object periodUid = listener.lastReportedTimeline.getUidOfPeriod(/* periodIndex= */ 0); EventWindowAndPeriodId prerollAd = @@ -1158,8 +1183,6 @@ public final class DefaultAnalyticsCollectorTest { periodUid, /* windowSequenceNumber= */ 0, /* nextAdGroupIndex= */ C.INDEX_UNSET)); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) .containsExactly( - WINDOW_0 /* setPlayWhenReady=true */, - WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* BUFFERING */, prerollAd /* READY */, prerollAd /* setPlayWhenReady=true */, @@ -1172,7 +1195,7 @@ public final class DefaultAnalyticsCollectorTest { assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) .containsExactly( WINDOW_0 /* PLAYLIST_CHANGED */, - prerollAd /* SOURCE_UPDATE (initial) */, + WINDOW_0 /* SOURCE_UPDATE (initial) */, contentAfterPreroll /* SOURCE_UPDATE (played preroll) */, contentAfterMidroll /* SOURCE_UPDATE (played midroll) */, contentAfterPostroll /* SOURCE_UPDATE (played postroll) */) @@ -1322,20 +1345,21 @@ public final class DefaultAnalyticsCollectorTest { } }, ExoPlayerTestRunner.VIDEO_FORMAT); - ActionSchedule actionSchedule = - new ActionSchedule.Builder(TAG) - .pause() - // Ensure everything is preloaded. - .waitForIsLoading(true) - .waitForIsLoading(false) - // Seek behind the midroll. - .seek(6 * C.MICROS_PER_SECOND) - // Wait until loading started again to assert loading events without flakiness. - .waitForIsLoading(true) - .play() - .waitForPlaybackState(Player.STATE_ENDED) - .build(); - TestAnalyticsListener listener = runAnalyticsTest(fakeMediaSource, actionSchedule); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.setMediaSource(fakeMediaSource); + player.prepare(); + // Ensure everything is preloaded. + runUntilIsLoading(player, /* expectedIsLoading= */ true); + runUntilIsLoading(player, /* expectedIsLoading= */ false); + // Seek behind the midroll. + player.seekTo(/* positionMs= */ 6_000); + // Wait until loading started again to assert loading events. + runUntilIsLoading(player, /* expectedIsLoading= */ true); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); Object periodUid = listener.lastReportedTimeline.getUidOfPeriod(/* periodIndex= */ 0); EventWindowAndPeriodId midrollAd = @@ -1357,8 +1381,6 @@ public final class DefaultAnalyticsCollectorTest { periodUid, /* windowSequenceNumber= */ 0, /* nextAdGroupIndex= */ C.INDEX_UNSET)); assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) .containsExactly( - WINDOW_0 /* setPlayWhenReady=true */, - WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* BUFFERING */, contentBeforeMidroll /* READY */, contentAfterMidroll /* BUFFERING */, @@ -1367,7 +1389,7 @@ public final class DefaultAnalyticsCollectorTest { contentAfterMidroll /* ENDED */) .inOrder(); assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) - .containsExactly(WINDOW_0 /* PLAYLIST_CHANGED */, contentBeforeMidroll /* SOURCE_UPDATE */); + .containsExactly(WINDOW_0 /* PLAYLIST_CHANGED */, WINDOW_0 /* SOURCE_UPDATE */); assertThat(listener.getEvents(EVENT_POSITION_DISCONTINUITY)) .containsExactly( contentAfterMidroll /* seek */, @@ -1435,21 +1457,17 @@ public final class DefaultAnalyticsCollectorTest { @Test public void notifyExternalEvents() throws Exception { MediaSource mediaSource = new FakeMediaSource(SINGLE_PERIOD_TIMELINE); - ActionSchedule actionSchedule = - new ActionSchedule.Builder(TAG) - .pause() - .waitForPlaybackState(Player.STATE_READY) - .executeRunnable( - new PlayerRunnable() { - @Override - public void run(ExoPlayer player) { - player.getAnalyticsCollector().notifySeekStarted(); - } - }) - .seek(/* positionMs= */ 0) - .play() - .build(); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource, actionSchedule); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.setMediaSource(mediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_READY); + player.getAnalyticsCollector().notifySeekStarted(); + player.seekTo(/* positionMs= */ 0); + player.play(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_SEEK_STARTED)).containsExactly(period0); @@ -1460,7 +1478,14 @@ public final class DefaultAnalyticsCollectorTest { public void drmEvents_singlePeriod() throws Exception { MediaSource mediaSource = new FakeMediaSource(SINGLE_PERIOD_TIMELINE, drmSessionManager, VIDEO_FORMAT_DRM_1); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.play(); + player.setMediaSource(mediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_DRM_SESSION_MANAGER_ERROR)).isEmpty(); @@ -1488,18 +1513,21 @@ public final class DefaultAnalyticsCollectorTest { SINGLE_PERIOD_TIMELINE, blockingDrmSessionManager, VIDEO_FORMAT_DRM_1), new FakeMediaSource( SINGLE_PERIOD_TIMELINE, blockingDrmSessionManager, VIDEO_FORMAT_DRM_1)); - TestAnalyticsListener listener = - runAnalyticsTest( - mediaSource, - // Wait for the media to be fully buffered before unblocking the DRM key request. This - // ensures both periods report the same load event (because period1's DRM session is - // already preacquired by the time the key load completes). - new ActionSchedule.Builder(TAG) - .waitForIsLoading(false) - .waitForIsLoading(true) - .waitForIsLoading(false) - .executeRunnable(mediaDrmCallback.keyCondition::open) - .build()); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.play(); + player.setMediaSource(mediaSource); + player.prepare(); + // Wait for the media to be fully buffered before unblocking the DRM key request. This + // ensures both periods report the same load event (because period1's DRM session is + // already preacquired by the time the key load completes). + runUntilIsLoading(player, /* expectedIsLoading= */ false); + runUntilIsLoading(player, /* expectedIsLoading= */ true); + runUntilIsLoading(player, /* expectedIsLoading= */ false); + mediaDrmCallback.keyCondition.open(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_DRM_SESSION_MANAGER_ERROR)).isEmpty(); @@ -1525,7 +1553,14 @@ public final class DefaultAnalyticsCollectorTest { SINGLE_PERIOD_TIMELINE, drmSessionManager, VIDEO_FORMAT_DRM_1.buildUpon().setDrmInitData(DRM_DATA_2).build())); - TestAnalyticsListener listener = runAnalyticsTest(mediaSource); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.play(); + player.setMediaSource(mediaSource); + player.prepare(); + runUntilPlaybackState(player, Player.STATE_ENDED); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_DRM_SESSION_MANAGER_ERROR)).isEmpty(); @@ -1552,13 +1587,16 @@ public final class DefaultAnalyticsCollectorTest { .build(mediaDrmCallback); MediaSource mediaSource = new FakeMediaSource(SINGLE_PERIOD_TIMELINE, failingDrmSessionManager, VIDEO_FORMAT_DRM_1); - TestAnalyticsListener listener = - runAnalyticsTest( - mediaSource, - new ActionSchedule.Builder(TAG) - .waitForIsLoading(false) - .executeRunnable(mediaDrmCallback.keyCondition::open) - .build()); + ExoPlayer player = setupPlayer(); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); + + player.play(); + player.setMediaSource(mediaSource); + player.prepare(); + runUntilIsLoading(player, /* expectedIsLoading= */ false); + mediaDrmCallback.keyCondition.open(); + runUntilError(player); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_DRM_SESSION_MANAGER_ERROR)).containsExactly(period0); @@ -1588,12 +1626,14 @@ public final class DefaultAnalyticsCollectorTest { } } }; + ExoPlayer player = setupPlayer(renderersFactory); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); - TestAnalyticsListener listener = - runAnalyticsTest( - new ConcatenatingMediaSource(source0, source1), - /* actionSchedule= */ null, - renderersFactory); + player.play(); + player.setMediaSource(new ConcatenatingMediaSource(source0, source1)); + player.prepare(); + runUntilError(player); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_ERROR)).containsExactly(period1); @@ -1622,12 +1662,14 @@ public final class DefaultAnalyticsCollectorTest { } } }; + ExoPlayer player = setupPlayer(renderersFactory); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); - TestAnalyticsListener listener = - runAnalyticsTest( - new ConcatenatingMediaSource(source0, source1), - /* actionSchedule= */ null, - renderersFactory); + player.play(); + player.setMediaSource(new ConcatenatingMediaSource(source0, source1)); + player.prepare(); + runUntilError(player); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_ERROR)).containsExactly(period1); @@ -1660,12 +1702,14 @@ public final class DefaultAnalyticsCollectorTest { } } }; + ExoPlayer player = setupPlayer(renderersFactory); + TestAnalyticsListener listener = new TestAnalyticsListener(); + player.addAnalyticsListener(listener); - TestAnalyticsListener listener = - runAnalyticsTest( - new ConcatenatingMediaSource(source, source), - /* actionSchedule= */ null, - renderersFactory); + player.play(); + player.setMediaSource(new ConcatenatingMediaSource(source, source)); + player.prepare(); + runUntilError(player); populateEventIds(listener.lastReportedTimeline); assertThat(listener.getEvents(EVENT_PLAYER_ERROR)).containsExactly(period1); @@ -1673,11 +1717,7 @@ public final class DefaultAnalyticsCollectorTest { @Test public void onEvents_isReportedWithCorrectEventTimes() throws Exception { - ExoPlayer player = - new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()).build(); - Surface surface = new Surface(new SurfaceTexture(/* texName= */ 0)); - player.setVideoSurface(surface); - + ExoPlayer player = setupPlayer(); AnalyticsListener listener = mock(AnalyticsListener.class); Format[] formats = new Format[] { @@ -1690,20 +1730,18 @@ public final class DefaultAnalyticsCollectorTest { player.setMediaSource(new FakeMediaSource(new FakeTimeline(), formats)); player.seekTo(2_000); player.setPlaybackParameters(new PlaybackParameters(/* speed= */ 2.0f)); - ShadowLooper.runMainLooperToNextTask(); - + runMainLooperToNextTask(); // Move to another item and fail with a third one to trigger events with different EventTimes. player.prepare(); - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY); + runUntilPlaybackState(player, Player.STATE_READY); player.addMediaSource(new FakeMediaSource(new FakeTimeline(), formats)); player.play(); TestPlayerRunHelper.runUntilPositionDiscontinuity( player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION); player.setMediaItem(MediaItem.fromUri("http://this-will-throw-an-exception.mp4")); - TestPlayerRunHelper.runUntilError(player); - ShadowLooper.runMainLooperToNextTask(); + runUntilError(player); + runMainLooperToNextTask(); player.release(); - surface.release(); // Verify that expected individual callbacks have been called and capture EventTimes. ArgumentCaptor individualTimelineChangedEventTimes = @@ -1928,48 +1966,6 @@ public final class DefaultAnalyticsCollectorTest { .inOrder(); } - private void populateEventIds(Timeline timeline) { - period0 = - new EventWindowAndPeriodId( - /* windowIndex= */ 0, - new MediaPeriodId( - timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 0)); - period0Seq0 = period0; - period0Seq1 = - new EventWindowAndPeriodId( - /* windowIndex= */ 0, - new MediaPeriodId( - timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 1)); - window1Period0Seq1 = - new EventWindowAndPeriodId( - /* windowIndex= */ 1, - new MediaPeriodId( - timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 1)); - if (timeline.getPeriodCount() > 1) { - period1 = - new EventWindowAndPeriodId( - /* windowIndex= */ 1, - new MediaPeriodId( - timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 1)); - period1Seq1 = period1; - period1Seq0 = - new EventWindowAndPeriodId( - /* windowIndex= */ 1, - new MediaPeriodId( - timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 0)); - period1Seq2 = - new EventWindowAndPeriodId( - /* windowIndex= */ 1, - new MediaPeriodId( - timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 2)); - window0Period1Seq0 = - new EventWindowAndPeriodId( - /* windowIndex= */ 0, - new MediaPeriodId( - timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 0)); - } - } - @Test public void recursiveListenerInvocation_arrivesInCorrectOrder() { AnalyticsCollector analyticsCollector = new DefaultAnalyticsCollector(Clock.DEFAULT); @@ -2027,13 +2023,12 @@ public final class DefaultAnalyticsCollectorTest { exoPlayer.setMediaSource( new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.VIDEO_FORMAT)); exoPlayer.prepare(); - TestPlayerRunHelper.runUntilPlaybackState(exoPlayer, Player.STATE_READY); - + runUntilPlaybackState(exoPlayer, Player.STATE_READY); // Release and add delay on releasing thread to verify timestamps of events. exoPlayer.release(); long releaseTimeMs = fakeClock.currentTimeMillis(); fakeClock.advanceTime(1); - ShadowLooper.idleMainLooper(); + idleMainLooper(); // Verify video disable events and release events arrived in order. ArgumentCaptor videoDisabledEventTime = @@ -2059,49 +2054,79 @@ public final class DefaultAnalyticsCollectorTest { assertThat(releasedEventTime.getValue().realtimeMs).isGreaterThan(videoDisableTimeMs); } - private static TestAnalyticsListener runAnalyticsTest(MediaSource mediaSource) throws Exception { - return runAnalyticsTest(mediaSource, /* actionSchedule= */ null); + private void populateEventIds(Timeline timeline) { + period0 = + new EventWindowAndPeriodId( + /* windowIndex= */ 0, + new MediaPeriodId( + timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 0)); + period0Seq0 = period0; + period0Seq1 = + new EventWindowAndPeriodId( + /* windowIndex= */ 0, + new MediaPeriodId( + timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 1)); + window1Period0Seq1 = + new EventWindowAndPeriodId( + /* windowIndex= */ 1, + new MediaPeriodId( + timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 1)); + if (timeline.getPeriodCount() > 1) { + period1 = + new EventWindowAndPeriodId( + /* windowIndex= */ 1, + new MediaPeriodId( + timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 1)); + period1Seq1 = period1; + period1Seq0 = + new EventWindowAndPeriodId( + /* windowIndex= */ 1, + new MediaPeriodId( + timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 0)); + period1Seq2 = + new EventWindowAndPeriodId( + /* windowIndex= */ 1, + new MediaPeriodId( + timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 2)); + window0Period1Seq0 = + new EventWindowAndPeriodId( + /* windowIndex= */ 0, + new MediaPeriodId( + timeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 0)); + } } - private static TestAnalyticsListener runAnalyticsTest( - MediaSource mediaSource, @Nullable ActionSchedule actionSchedule) throws Exception { - RenderersFactory renderersFactory = - (eventHandler, + private static ExoPlayer setupPlayer() { + Clock clock = new FakeClock(/* isAutoAdvancing= */ true); + return setupPlayer( + /* renderersFactory= */ (eventHandler, videoRendererEventListener, audioRendererEventListener, textRendererOutput, - metadataRendererOutput) -> - new Renderer[] { - new FakeVideoRenderer(eventHandler, videoRendererEventListener), - new FakeAudioRenderer(eventHandler, audioRendererEventListener) - }; - return runAnalyticsTest(mediaSource, actionSchedule, renderersFactory); + metadataRendererOutput) -> { + HandlerWrapper clockAwareHandler = + clock.createHandler(eventHandler.getLooper(), /* callback= */ null); + return new Renderer[] { + new FakeVideoRenderer(clockAwareHandler, videoRendererEventListener), + new FakeAudioRenderer(clockAwareHandler, audioRendererEventListener) + }; + }, + clock); } - private static TestAnalyticsListener runAnalyticsTest( - MediaSource mediaSource, - @Nullable ActionSchedule actionSchedule, - RenderersFactory renderersFactory) - throws Exception { + private static ExoPlayer setupPlayer(RenderersFactory renderersFactory) { + return setupPlayer(renderersFactory, new FakeClock(/* isAutoAdvancing= */ true)); + } + + private static ExoPlayer setupPlayer(RenderersFactory renderersFactory, Clock clock) { Surface surface = new Surface(new SurfaceTexture(/* texName= */ 0)); - TestAnalyticsListener listener = new TestAnalyticsListener(); - try { - new ExoPlayerTestRunner.Builder(ApplicationProvider.getApplicationContext()) - .setMediaSources(mediaSource) - .setRenderersFactory(renderersFactory) - .setVideoSurface(surface) - .setAnalyticsListener(listener) - .setActionSchedule(actionSchedule) - .build() - .start() - .blockUntilActionScheduleFinished(TIMEOUT_MS) - .blockUntilEnded(TIMEOUT_MS); - } catch (ExoPlaybackException e) { - // Ignore ExoPlaybackException as these may be expected. - } finally { - surface.release(); - } - return listener; + ExoPlayer player = + new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()) + .setClock(clock) + .setRenderersFactory(renderersFactory) + .build(); + player.setVideoSurface(surface); + return player; } private static final class EventWindowAndPeriodId { 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 aa878c3d4b..66cb4c9ddf 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 @@ -89,6 +89,30 @@ public class TestPlayerRunHelper { } } + /** + * Runs tasks of the main {@link Looper} until {@link Player#isLoading()} matches the 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 expectedIsLoading The expected value for {@link Player#isLoading()}. + * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is + * exceeded. + */ + public static void runUntilIsLoading(Player player, boolean expectedIsLoading) + throws TimeoutException { + verifyMainTestThread(player); + if (player instanceof ExoPlayer) { + verifyPlaybackThreadIsAlive((ExoPlayer) player); + } + runMainLooperUntil( + () -> player.isLoading() == expectedIsLoading || player.getPlayerError() != null); + if (player.getPlayerError() != null) { + throw new IllegalStateException(player.getPlayerError()); + } + } + /** * Runs tasks of the main {@link Looper} until {@link Player#getCurrentTimeline()} matches the * expected timeline or a playback error occurs. diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAudioRenderer.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAudioRenderer.java index eb02f675c2..4d23be2261 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAudioRenderer.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAudioRenderer.java @@ -16,24 +16,26 @@ package com.google.android.exoplayer2.testutil; -import android.os.Handler; import android.os.SystemClock; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.audio.AudioRendererEventListener; import com.google.android.exoplayer2.decoder.DecoderCounters; +import com.google.android.exoplayer2.util.HandlerWrapper; /** A {@link FakeRenderer} that supports {@link C#TRACK_TYPE_AUDIO}. */ public class FakeAudioRenderer extends FakeRenderer { - private final AudioRendererEventListener.EventDispatcher eventDispatcher; + private final HandlerWrapper handler; + private final AudioRendererEventListener eventListener; private final DecoderCounters decoderCounters; private boolean notifiedPositionAdvancing; - public FakeAudioRenderer(Handler handler, AudioRendererEventListener eventListener) { + public FakeAudioRenderer(HandlerWrapper handler, AudioRendererEventListener eventListener) { super(C.TRACK_TYPE_AUDIO); - eventDispatcher = new AudioRendererEventListener.EventDispatcher(handler, eventListener); + this.handler = handler; + this.eventListener = eventListener; decoderCounters = new DecoderCounters(); } @@ -41,30 +43,33 @@ public class FakeAudioRenderer extends FakeRenderer { protected void onEnabled(boolean joining, boolean mayRenderStartOfStream) throws ExoPlaybackException { super.onEnabled(joining, mayRenderStartOfStream); - eventDispatcher.enabled(decoderCounters); + handler.post(() -> eventListener.onAudioEnabled(decoderCounters)); notifiedPositionAdvancing = false; } @Override protected void onDisabled() { super.onDisabled(); - eventDispatcher.disabled(decoderCounters); + handler.post(() -> eventListener.onAudioDisabled(decoderCounters)); } @Override protected void onFormatChanged(Format format) { - eventDispatcher.inputFormatChanged(format, /* decoderReuseEvaluation= */ null); - eventDispatcher.decoderInitialized( - /* decoderName= */ "fake.audio.decoder", - /* initializedTimestampMs= */ SystemClock.elapsedRealtime(), - /* initializationDurationMs= */ 0); + handler.post( + () -> eventListener.onAudioInputFormatChanged(format, /* decoderReuseEvaluation= */ null)); + handler.post( + () -> + eventListener.onAudioDecoderInitialized( + /* decoderName= */ "fake.audio.decoder", + /* initializedTimestampMs= */ SystemClock.elapsedRealtime(), + /* initializationDurationMs= */ 0)); } @Override protected boolean shouldProcessBuffer(long bufferTimeUs, long playbackPositionUs) { boolean shouldProcess = super.shouldProcessBuffer(bufferTimeUs, playbackPositionUs); if (shouldProcess && !notifiedPositionAdvancing) { - eventDispatcher.positionAdvancing(System.currentTimeMillis()); + handler.post(() -> eventListener.onAudioPositionAdvancing(System.currentTimeMillis())); notifiedPositionAdvancing = true; } return shouldProcess; diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeVideoRenderer.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeVideoRenderer.java index ad30d53bae..41303e12ce 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeVideoRenderer.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeVideoRenderer.java @@ -16,7 +16,6 @@ package com.google.android.exoplayer2.testutil; -import android.os.Handler; import android.os.SystemClock; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; @@ -25,6 +24,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.android.exoplayer2.video.VideoRendererEventListener; import com.google.android.exoplayer2.video.VideoSize; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -32,7 +32,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** A {@link FakeRenderer} that supports {@link C#TRACK_TYPE_VIDEO}. */ public class FakeVideoRenderer extends FakeRenderer { - private final VideoRendererEventListener.EventDispatcher eventDispatcher; + private final HandlerWrapper handler; + private final VideoRendererEventListener eventListener; private final DecoderCounters decoderCounters; private @MonotonicNonNull Format format; @Nullable private Object output; @@ -41,9 +42,10 @@ public class FakeVideoRenderer extends FakeRenderer { private boolean mayRenderFirstFrameAfterEnableIfNotStarted; private boolean renderedFirstFrameAfterEnable; - public FakeVideoRenderer(Handler handler, VideoRendererEventListener eventListener) { + public FakeVideoRenderer(HandlerWrapper handler, VideoRendererEventListener eventListener) { super(C.TRACK_TYPE_VIDEO); - eventDispatcher = new VideoRendererEventListener.EventDispatcher(handler, eventListener); + this.handler = handler; + this.eventListener = eventListener; decoderCounters = new DecoderCounters(); } @@ -51,7 +53,7 @@ public class FakeVideoRenderer extends FakeRenderer { protected void onEnabled(boolean joining, boolean mayRenderStartOfStream) throws ExoPlaybackException { super.onEnabled(joining, mayRenderStartOfStream); - eventDispatcher.enabled(decoderCounters); + handler.post(() -> eventListener.onVideoEnabled(decoderCounters)); mayRenderFirstFrameAfterEnableIfNotStarted = mayRenderStartOfStream; renderedFirstFrameAfterEnable = false; } @@ -67,15 +69,17 @@ public class FakeVideoRenderer extends FakeRenderer { @Override protected void onStopped() { super.onStopped(); - eventDispatcher.droppedFrames(/* droppedFrameCount= */ 0, /* elapsedMs= */ 0); - eventDispatcher.reportVideoFrameProcessingOffset( - /* totalProcessingOffsetUs= */ 400000, /* frameCount= */ 10); + handler.post(() -> eventListener.onDroppedFrames(/* count= */ 0, /* elapsedMs= */ 0)); + handler.post( + () -> + eventListener.onVideoFrameProcessingOffset( + /* totalProcessingOffsetUs= */ 400000, /* frameCount= */ 10)); } @Override protected void onDisabled() { super.onDisabled(); - eventDispatcher.disabled(decoderCounters); + handler.post(() -> eventListener.onVideoDisabled(decoderCounters)); } @Override @@ -86,11 +90,14 @@ public class FakeVideoRenderer extends FakeRenderer { @Override protected void onFormatChanged(Format format) { - eventDispatcher.inputFormatChanged(format, /* decoderReuseEvaluation= */ null); - eventDispatcher.decoderInitialized( - /* decoderName= */ "fake.video.decoder", - /* initializedTimestampMs= */ SystemClock.elapsedRealtime(), - /* initializationDurationMs= */ 0); + handler.post( + () -> eventListener.onVideoInputFormatChanged(format, /* decoderReuseEvaluation= */ null)); + handler.post( + () -> + eventListener.onVideoDecoderInitialized( + /* decoderName= */ "fake.video.decoder", + /* initializedTimestampMs= */ SystemClock.elapsedRealtime(), + /* initializationDurationMs= */ 0)); this.format = format; } @@ -131,10 +138,18 @@ public class FakeVideoRenderer extends FakeRenderer { @Nullable Object output = this.output; if (shouldProcess && !renderedFirstFrameAfterReset && output != null) { @MonotonicNonNull Format format = Assertions.checkNotNull(this.format); - eventDispatcher.videoSizeChanged( - new VideoSize( - format.width, format.height, format.rotationDegrees, format.pixelWidthHeightRatio)); - eventDispatcher.renderedFirstFrame(output); + handler.post( + () -> + eventListener.onVideoSizeChanged( + new VideoSize( + format.width, + format.height, + format.rotationDegrees, + format.pixelWidthHeightRatio))); + handler.post( + () -> + eventListener.onRenderedFirstFrame( + output, /* renderTimeMs= */ SystemClock.elapsedRealtime())); renderedFirstFrameAfterReset = true; renderedFirstFrameAfterEnable = true; } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestExoPlayerBuilder.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestExoPlayerBuilder.java index 034053d1b8..be5dc85eed 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestExoPlayerBuilder.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestExoPlayerBuilder.java @@ -33,6 +33,7 @@ import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Clock; +import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.errorprone.annotations.CanIgnoreReturnValue; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -297,13 +298,16 @@ public class TestExoPlayerBuilder { videoRendererEventListener, audioRendererEventListener, textRendererOutput, - metadataRendererOutput) -> - renderers != null - ? renderers - : new Renderer[] { - new FakeVideoRenderer(eventHandler, videoRendererEventListener), - new FakeAudioRenderer(eventHandler, audioRendererEventListener) - }; + metadataRendererOutput) -> { + HandlerWrapper clockAwareHandler = + clock.createHandler(eventHandler.getLooper(), /* callback= */ null); + return renderers != null + ? renderers + : new Renderer[] { + new FakeVideoRenderer(clockAwareHandler, videoRendererEventListener), + new FakeAudioRenderer(clockAwareHandler, audioRendererEventListener) + }; + }; } ExoPlayer.Builder builder = From 07d1970f3560aa584abda7f57bcfd87af57b6f70 Mon Sep 17 00:00:00 2001 From: huangdarwin Date: Fri, 25 Nov 2022 15:59:49 +0000 Subject: [PATCH 008/183] HDR: Add COLOR_TRANSFER_LINEAR in C.java. This is more clear than using Format.NO_VALUE, when we do actually intend for an output value. Also, fix @see formatting by using summary fragments instead, and add an error output for OETF and EOTF transfer functions. PiperOrigin-RevId: 490910229 --- .../java/com/google/android/exoplayer2/C.java | 25 +++++++++++-------- .../exoplayer2/util/MediaFormatUtil.java | 3 ++- .../android/exoplayer2/video/ColorInfo.java | 17 ++++++++----- .../shaders/fragment_shader_oetf_es3.glsl | 12 +++++++-- ...hader_transformation_external_yuv_es3.glsl | 7 +++++- 5 files changed, 43 insertions(+), 21 deletions(-) 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 c2ce271b7a..d6d074c736 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 @@ -1048,24 +1048,27 @@ public final class C { // LINT.IfChange(color_transfer) /** * Video color transfer characteristics. One of {@link Format#NO_VALUE}, {@link - * #COLOR_TRANSFER_SDR}, {@link #COLOR_TRANSFER_ST2084} or {@link #COLOR_TRANSFER_HLG}. + * #COLOR_TRANSFER_LINEAR}, {@link #COLOR_TRANSFER_SDR}, {@link #COLOR_TRANSFER_ST2084} or {@link + * #COLOR_TRANSFER_HLG}. */ @Documented @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) - @IntDef({Format.NO_VALUE, COLOR_TRANSFER_SDR, COLOR_TRANSFER_ST2084, COLOR_TRANSFER_HLG}) + @IntDef({ + Format.NO_VALUE, + COLOR_TRANSFER_LINEAR, + COLOR_TRANSFER_SDR, + COLOR_TRANSFER_ST2084, + COLOR_TRANSFER_HLG + }) public @interface ColorTransfer {} - /** - * @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO - */ + /** See {@link MediaFormat#COLOR_TRANSFER_LINEAR}. */ + public static final int COLOR_TRANSFER_LINEAR = MediaFormat.COLOR_TRANSFER_LINEAR; + /** See {@link MediaFormat#COLOR_TRANSFER_SDR_VIDEO}. */ public static final int COLOR_TRANSFER_SDR = MediaFormat.COLOR_TRANSFER_SDR_VIDEO; - /** - * @see MediaFormat#COLOR_TRANSFER_ST2084 - */ + /** See {@link MediaFormat#COLOR_TRANSFER_ST2084}. */ public static final int COLOR_TRANSFER_ST2084 = MediaFormat.COLOR_TRANSFER_ST2084; - /** - * @see MediaFormat#COLOR_TRANSFER_HLG - */ + /** See {@link MediaFormat#COLOR_TRANSFER_HLG}. */ public static final int COLOR_TRANSFER_HLG = MediaFormat.COLOR_TRANSFER_HLG; // LINT.IfChange(color_range) diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/MediaFormatUtil.java b/library/common/src/main/java/com/google/android/exoplayer2/util/MediaFormatUtil.java index 758f535dd8..903692c439 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/MediaFormatUtil.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/MediaFormatUtil.java @@ -321,7 +321,8 @@ public final class MediaFormatUtil { /** Whether this is a valid {@link C.ColorTransfer} instance. */ private static boolean isValidColorTransfer(int colorTransfer) { // LINT.IfChange(color_transfer) - return colorTransfer == C.COLOR_TRANSFER_SDR + return colorTransfer == C.COLOR_TRANSFER_LINEAR + || colorTransfer == C.COLOR_TRANSFER_SDR || colorTransfer == C.COLOR_TRANSFER_ST2084 || colorTransfer == C.COLOR_TRANSFER_HLG || colorTransfer == Format.NO_VALUE; 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 9215907a39..58213832bf 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 @@ -90,11 +90,16 @@ public final class ColorInfo implements Bundleable { } } - /** Returns whether the {@code ColorInfo} uses an HDR {@link C.ColorTransfer}. */ + /** + * Returns whether the {@code ColorInfo} uses an HDR {@link C.ColorTransfer}. + * + *

{@link C#COLOR_TRANSFER_LINEAR} is not considered to be an HDR {@link C.ColorTransfer}, + * because it may represent either SDR or HDR contents. + */ public static boolean isTransferHdr(@Nullable ColorInfo colorInfo) { return colorInfo != null - && colorInfo.colorTransfer != Format.NO_VALUE - && colorInfo.colorTransfer != C.COLOR_TRANSFER_SDR; + && (colorInfo.colorTransfer == C.COLOR_TRANSFER_HLG + || colorInfo.colorTransfer == C.COLOR_TRANSFER_ST2084); } /** @@ -110,9 +115,9 @@ public final class ColorInfo implements Bundleable { public final @C.ColorRange int colorRange; /** - * The color transfer characteristics of the video. Valid values are {@link C#COLOR_TRANSFER_HLG}, - * {@link C#COLOR_TRANSFER_ST2084}, {@link C#COLOR_TRANSFER_SDR} or {@link Format#NO_VALUE} if - * unknown. + * The color transfer characteristics of the video. Valid values are {@link + * C#COLOR_TRANSFER_LINEAR}, {@link C#COLOR_TRANSFER_HLG}, {@link C#COLOR_TRANSFER_ST2084}, {@link + * C#COLOR_TRANSFER_SDR} or {@link Format#NO_VALUE} if unknown. */ public final @C.ColorTransfer int colorTransfer; diff --git a/library/effect/src/main/assets/shaders/fragment_shader_oetf_es3.glsl b/library/effect/src/main/assets/shaders/fragment_shader_oetf_es3.glsl index 42e14e0eb8..31dd05b80a 100644 --- a/library/effect/src/main/assets/shaders/fragment_shader_oetf_es3.glsl +++ b/library/effect/src/main/assets/shaders/fragment_shader_oetf_es3.glsl @@ -79,12 +79,20 @@ highp vec3 pqOetf(highp vec3 linearColor) { highp vec3 getElectricalColor(highp vec3 linearColor) { // LINT.IfChange(color_transfer) const int COLOR_TRANSFER_ST2084 = 6; - return (uOetfColorTransfer == COLOR_TRANSFER_ST2084) ? - pqOetf(linearColor) : hlgOetf(linearColor); + const int COLOR_TRANSFER_HLG = 7; + if (uOetfColorTransfer == COLOR_TRANSFER_ST2084) { + return pqOetf(linearColor); + } else if (uOetfColorTransfer == COLOR_TRANSFER_HLG) { + return hlgOetf(linearColor); + } else { + // Output red as an obviously visible error. + return vec3(1.0, 0.0, 0.0); + } } void main() { vec4 inputColor = texture(uTexSampler, vTexSamplingCoord); + // transformedColors is an optical color. vec4 transformedColors = uRgbMatrix * vec4(inputColor.rgb, 1); outColor = vec4(getElectricalColor(transformedColors.rgb), inputColor.a); } diff --git a/library/effect/src/main/assets/shaders/fragment_shader_transformation_external_yuv_es3.glsl b/library/effect/src/main/assets/shaders/fragment_shader_transformation_external_yuv_es3.glsl index aa238028fc..f06e6967e1 100644 --- a/library/effect/src/main/assets/shaders/fragment_shader_transformation_external_yuv_es3.glsl +++ b/library/effect/src/main/assets/shaders/fragment_shader_transformation_external_yuv_es3.glsl @@ -86,12 +86,17 @@ highp vec3 getOpticalColor(highp vec3 electricalColor) { const int COLOR_TRANSFER_ST2084 = 6; const int COLOR_TRANSFER_HLG = 7; + const int FORMAT_NO_VALUE = -1; + if (uEotfColorTransfer == COLOR_TRANSFER_ST2084) { return pqEotf(electricalColor); } else if (uEotfColorTransfer == COLOR_TRANSFER_HLG) { return hlgEotf(electricalColor); - } else { + } else if (uEotfColorTransfer == FORMAT_NO_VALUE) { return electricalColor; + } else { + // Output red as an obviously visible error. + return vec3(1.0, 0.0, 0.0); } } From ed8c196e2eb36eefef9952d255cb6355807b9e9f Mon Sep 17 00:00:00 2001 From: ibaker Date: Fri, 25 Nov 2022 17:55:12 +0000 Subject: [PATCH 009/183] Clean up javadoc on `Metadata.Entry.populateMediaMetadata` Remove self-links, and remove section that is documenting internal ordering behaviour of [`SimpleBasePlayer.getCombinedMediaMetadata`](https://github.com/google/ExoPlayer/blob/bb270c62cf2f7a1570fe22f87bb348a2d5e94dcf/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java#L1770) rather than anything specifically about this method. #minor-release PiperOrigin-RevId: 490923719 --- .../com/google/android/exoplayer2/metadata/Metadata.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) 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 2e98e99f0e..9bbe0e8a95 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 @@ -52,11 +52,8 @@ public final class Metadata implements Parcelable { } /** - * Updates the {@link MediaMetadata.Builder} with the type specific values stored in this Entry. - * - *

The order of the {@link Entry} objects in the {@link Metadata} matters. If two {@link - * Entry} entries attempt to populate the same {@link MediaMetadata} field, then the last one in - * the list is used. + * Updates the {@link MediaMetadata.Builder} with the type-specific values stored in this {@code + * Entry}. * * @param builder The builder to be updated. */ From 2977bef872d7f3a1611fd6e8a45931388ea21c9f Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 28 Nov 2022 09:25:18 +0000 Subject: [PATCH 010/183] Ensure messages sent on a dead thread don't block FakeClock execution FakeClock keeps an internal list of messages to be executed to ensure deterministic serialization. The next message from the list is triggered by a separate helper message sent to the real Handler. However, if the target HandlerThread is no longer alive (e.g. when it quit itself during the message execution), this helper message is never executed and the entire message execution chain is stuck forever. This can be solved by checking the return values of Hander.post or Handler.sendMessage, which are false if the message won't be delivered. If the messages are not delivered, we can unblock the chain by marking the message as complete and triggering the next one. PiperOrigin-RevId: 491275031 --- .../exoplayer2/testutil/FakeClock.java | 17 +++--- .../exoplayer2/testutil/FakeClockTest.java | 54 +++++++++++++++++-- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java index b9ae509619..0f8238f234 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java @@ -242,16 +242,19 @@ public class FakeClock implements Clock { } handlerMessages.remove(messageIndex); waitingForMessage = true; + boolean messageSent; + Handler realHandler = message.handler.handler; if (message.runnable != null) { - message.handler.handler.post(message.runnable); + messageSent = realHandler.post(message.runnable); } else { - message - .handler - .handler - .obtainMessage(message.what, message.arg1, message.arg2, message.obj) - .sendToTarget(); + messageSent = + realHandler.sendMessage( + realHandler.obtainMessage(message.what, message.arg1, message.arg2, message.obj)); + } + messageSent &= message.handler.internalHandler.post(this::onMessageHandled); + if (!messageSent) { + onMessageHandled(); } - message.handler.internalHandler.post(this::onMessageHandled); } private synchronized void onMessageHandled() { diff --git a/testutils/src/test/java/com/google/android/exoplayer2/testutil/FakeClockTest.java b/testutils/src/test/java/com/google/android/exoplayer2/testutil/FakeClockTest.java index 830d4fce22..48d4abe858 100644 --- a/testutils/src/test/java/com/google/android/exoplayer2/testutil/FakeClockTest.java +++ b/testutils/src/test/java/com/google/android/exoplayer2/testutil/FakeClockTest.java @@ -29,6 +29,7 @@ import com.google.common.base.Objects; import com.google.common.collect.Iterables; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.shadows.ShadowLooper; @@ -40,6 +41,7 @@ public final class FakeClockTest { @Test public void currentTimeMillis_withoutBootTime() { FakeClock fakeClock = new FakeClock(/* initialTimeMs= */ 10); + assertThat(fakeClock.currentTimeMillis()).isEqualTo(10); } @@ -48,6 +50,7 @@ public final class FakeClockTest { FakeClock fakeClock = new FakeClock( /* bootTimeMs= */ 150, /* initialTimeMs= */ 200, /* isAutoAdvancing= */ false); + assertThat(fakeClock.currentTimeMillis()).isEqualTo(350); } @@ -55,17 +58,24 @@ public final class FakeClockTest { public void currentTimeMillis_afterAdvanceTime_currentTimeHasAdvanced() { FakeClock fakeClock = new FakeClock(/* bootTimeMs= */ 100, /* initialTimeMs= */ 50, /* isAutoAdvancing= */ false); + fakeClock.advanceTime(/* timeDiffMs */ 250); + assertThat(fakeClock.currentTimeMillis()).isEqualTo(400); } @Test public void elapsedRealtime_afterAdvanceTime_timeHasAdvanced() { FakeClock fakeClock = new FakeClock(2000); + assertThat(fakeClock.elapsedRealtime()).isEqualTo(2000); + fakeClock.advanceTime(500); + assertThat(fakeClock.elapsedRealtime()).isEqualTo(2500); + fakeClock.advanceTime(0); + assertThat(fakeClock.elapsedRealtime()).isEqualTo(2500); } @@ -86,6 +96,7 @@ public final class FakeClockTest { .sendToTarget(); ShadowLooper.idleMainLooper(); shadowOf(handler.getLooper()).idle(); + handlerThread.quitSafely(); assertThat(callback.messages) .containsExactly( @@ -126,6 +137,7 @@ public final class FakeClockTest { fakeClock.advanceTime(50); shadowOf(handler.getLooper()).idle(); + handlerThread.quitSafely(); assertThat(callback.messages).hasSize(4); assertThat(Iterables.getLast(callback.messages)) @@ -146,6 +158,7 @@ public final class FakeClockTest { handler.obtainMessage(/* what= */ 4).sendToTarget(); ShadowLooper.idleMainLooper(); shadowOf(handler.getLooper()).idle(); + handlerThread.quitSafely(); assertThat(callback.messages) .containsExactly( @@ -192,6 +205,8 @@ public final class FakeClockTest { fakeClock.advanceTime(1000); shadowOf(handler.getLooper()).idle(); assertTestRunnableStates(new boolean[] {true, true, true, true, true}, testRunnables); + + handlerThread.quitSafely(); } @Test @@ -203,7 +218,6 @@ public final class FakeClockTest { HandlerWrapper handler = fakeClock.createHandler(handlerThread.getLooper(), callback); TestCallback otherCallback = new TestCallback(); HandlerWrapper otherHandler = fakeClock.createHandler(handlerThread.getLooper(), otherCallback); - TestRunnable testRunnable1 = new TestRunnable(); TestRunnable testRunnable2 = new TestRunnable(); Object messageToken = new Object(); @@ -216,10 +230,10 @@ public final class FakeClockTest { handler.removeMessages(/* what= */ 2); handler.removeCallbacksAndMessages(messageToken); - fakeClock.advanceTime(50); ShadowLooper.idleMainLooper(); shadowOf(handlerThread.getLooper()).idle(); + handlerThread.quitSafely(); assertThat(callback.messages) .containsExactly( @@ -242,7 +256,6 @@ public final class FakeClockTest { HandlerWrapper handler = fakeClock.createHandler(handlerThread.getLooper(), callback); TestCallback otherCallback = new TestCallback(); HandlerWrapper otherHandler = fakeClock.createHandler(handlerThread.getLooper(), otherCallback); - TestRunnable testRunnable1 = new TestRunnable(); TestRunnable testRunnable2 = new TestRunnable(); Object messageToken = new Object(); @@ -254,15 +267,14 @@ public final class FakeClockTest { otherHandler.sendEmptyMessage(/* what= */ 1); handler.removeCallbacksAndMessages(/* token= */ null); - fakeClock.advanceTime(50); ShadowLooper.idleMainLooper(); shadowOf(handlerThread.getLooper()).idle(); + handlerThread.quitSafely(); assertThat(callback.messages).isEmpty(); assertThat(testRunnable1.hasRun).isFalse(); assertThat(testRunnable2.hasRun).isFalse(); - // Assert that message on other handler wasn't removed. assertThat(otherCallback.messages) .containsExactly( @@ -295,6 +307,7 @@ public final class FakeClockTest { }); ShadowLooper.idleMainLooper(); shadowOf(handler.getLooper()).idle(); + handlerThread.quitSafely(); assertThat(clockTimes).containsExactly(0L, 20L, 50L, 70L, 100L).inOrder(); } @@ -333,6 +346,8 @@ public final class FakeClockTest { }); ShadowLooper.idleMainLooper(); messagesFinished.block(); + handlerThread1.quitSafely(); + handlerThread2.quitSafely(); assertThat(executionOrder).containsExactly(1, 2, 3, 4, 5, 6, 7, 8).inOrder(); } @@ -368,10 +383,39 @@ public final class FakeClockTest { ShadowLooper.idleMainLooper(); shadowOf(handler1.getLooper()).idle(); shadowOf(handler2.getLooper()).idle(); + handlerThread1.quitSafely(); + handlerThread2.quitSafely(); assertThat(executionOrder).containsExactly(1, 2, 3, 4).inOrder(); } + @Test + public void createHandler_messageOnDeadThread_doesNotBlockExecution() { + HandlerThread handlerThread1 = new HandlerThread("FakeClockTest"); + handlerThread1.start(); + HandlerThread handlerThread2 = new HandlerThread("FakeClockTest"); + handlerThread2.start(); + FakeClock fakeClock = new FakeClock(/* initialTimeMs= */ 0); + HandlerWrapper handler1 = + fakeClock.createHandler(handlerThread1.getLooper(), /* callback= */ null); + HandlerWrapper handler2 = + fakeClock.createHandler(handlerThread2.getLooper(), /* callback= */ null); + + ConditionVariable messagesFinished = new ConditionVariable(); + AtomicBoolean messageOnDeadThreadExecuted = new AtomicBoolean(); + handler1.post( + () -> { + handlerThread1.quitSafely(); + handler1.post(() -> messageOnDeadThreadExecuted.set(true)); + handler2.post(messagesFinished::open); + }); + ShadowLooper.idleMainLooper(); + messagesFinished.block(); + handlerThread2.quitSafely(); + + assertThat(messageOnDeadThreadExecuted.get()).isFalse(); + } + private static void assertTestRunnableStates(boolean[] states, TestRunnable[] testRunnables) { for (int i = 0; i < testRunnables.length; i++) { assertThat(testRunnables[i].hasRun).isEqualTo(states[i]); From bf77290fbe78aa25698c1a7082b2a18cd7f1b06c Mon Sep 17 00:00:00 2001 From: ibaker Date: Mon, 28 Nov 2022 11:33:36 +0000 Subject: [PATCH 011/183] Split up `Id3DecoderTest` methods It's clearer if each test method follows the Arrange/Act/Assert pattern PiperOrigin-RevId: 491299379 --- .../metadata/id3/Id3DecoderTest.java | 198 ++++++++++++------ 1 file changed, 139 insertions(+), 59 deletions(-) diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/metadata/id3/Id3DecoderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/metadata/id3/Id3DecoderTest.java index 40c8c74d18..c86d1235a7 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/metadata/id3/Id3DecoderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/metadata/id3/Id3DecoderTest.java @@ -37,8 +37,7 @@ public final class Id3DecoderTest { private static final int ID3_TEXT_ENCODING_UTF_8 = 3; @Test - public void decodeTxxxFrame() { - // Test UTF-8. + public void decodeTxxxFrame_utf8() { byte[] rawId3 = buildSingleFrameTag( "TXXX", @@ -47,52 +46,74 @@ public final class Id3DecoderTest { 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); TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0); assertThat(textInformationFrame.id).isEqualTo("TXXX"); assertThat(textInformationFrame.description).isEmpty(); assertThat(textInformationFrame.values.get(0)).isEqualTo("mdialog_VINDICO1527664_start"); + } - // Test UTF-16. - rawId3 = + @Test + public void decodeTxxxFrame_utf16() { + byte[] rawId3 = buildSingleFrameTag( "TXXX", new byte[] { 1, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 0 }); - metadata = decoder.decode(rawId3, rawId3.length); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); + assertThat(metadata.length()).isEqualTo(1); - textInformationFrame = (TextInformationFrame) metadata.get(0); + TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0); assertThat(textInformationFrame.id).isEqualTo("TXXX"); assertThat(textInformationFrame.description).isEqualTo("Hello World"); assertThat(textInformationFrame.values).containsExactly(""); + } - // Test multiple values. - rawId3 = + @Test + public void decodeTxxxFrame_multipleValues() { + byte[] rawId3 = buildSingleFrameTag( "TXXX", new byte[] { 1, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 0, 0, 70, 0, 111, 0, 111, 0, 0, 0, 66, 0, 97, 0, 114, 0, 0 }); - metadata = decoder.decode(rawId3, rawId3.length); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); + assertThat(metadata.length()).isEqualTo(1); - textInformationFrame = (TextInformationFrame) metadata.get(0); + TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0); assertThat(textInformationFrame.description).isEqualTo("Hello World"); assertThat(textInformationFrame.values).containsExactly("Foo", "Bar").inOrder(); + } + + @Test + public void decodeTxxxFrame_empty() { + byte[] rawId3 = buildSingleFrameTag("TXXX", new byte[0]); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test empty. - rawId3 = buildSingleFrameTag("TXXX", new byte[0]); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(0); + } + + @Test + public void decodeTxxxFrame_encodingByteOnly() { + byte[] rawId3 = buildSingleFrameTag("TXXX", new byte[] {ID3_TEXT_ENCODING_UTF_8}); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test encoding byte only. - rawId3 = buildSingleFrameTag("TXXX", new byte[] {ID3_TEXT_ENCODING_UTF_8}); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); - textInformationFrame = (TextInformationFrame) metadata.get(0); + TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0); assertThat(textInformationFrame.id).isEqualTo("TXXX"); assertThat(textInformationFrame.description).isEmpty(); assertThat(textInformationFrame.values).containsExactly(""); @@ -104,31 +125,49 @@ public final class Id3DecoderTest { 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); TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0); assertThat(textInformationFrame.id).isEqualTo("TIT2"); assertThat(textInformationFrame.description).isNull(); assertThat(textInformationFrame.values.size()).isEqualTo(1); assertThat(textInformationFrame.values.get(0)).isEqualTo("Hello World"); + } + @Test + public void decodeTextInformationFrame_multipleValues() { // Test multiple values. - rawId3 = buildSingleFrameTag("TIT2", new byte[] {3, 70, 111, 111, 0, 66, 97, 114, 0}); - metadata = decoder.decode(rawId3, rawId3.length); + byte[] rawId3 = buildSingleFrameTag("TIT2", new byte[] {3, 70, 111, 111, 0, 66, 97, 114, 0}); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); + assertThat(metadata.length()).isEqualTo(1); - textInformationFrame = (TextInformationFrame) metadata.get(0); + TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0); assertThat(textInformationFrame.values).containsExactly("Foo", "Bar").inOrder(); + } + + @Test + public void decodeTextInformationFrame_empty() { + byte[] rawId3 = buildSingleFrameTag("TIT2", new byte[0]); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test empty. - rawId3 = buildSingleFrameTag("TIT2", new byte[0]); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(0); + } + + @Test + public void decodeTextInformationFrame_encodingByteOnly() { + byte[] rawId3 = buildSingleFrameTag("TIT2", new byte[] {ID3_TEXT_ENCODING_UTF_8}); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test encoding byte only. - rawId3 = buildSingleFrameTag("TIT2", new byte[] {ID3_TEXT_ENCODING_UTF_8}); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); - textInformationFrame = (TextInformationFrame) metadata.get(0); + TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0); assertThat(textInformationFrame.id).isEqualTo("TIT2"); assertThat(textInformationFrame.description).isNull(); assertThat(textInformationFrame.values).containsExactly(""); @@ -172,23 +211,35 @@ public final class Id3DecoderTest { 102 }); Id3Decoder decoder = new Id3Decoder(); + Metadata metadata = decoder.decode(rawId3, rawId3.length); + assertThat(metadata.length()).isEqualTo(1); UrlLinkFrame urlLinkFrame = (UrlLinkFrame) metadata.get(0); assertThat(urlLinkFrame.id).isEqualTo("WXXX"); assertThat(urlLinkFrame.description).isEqualTo("test"); assertThat(urlLinkFrame.url).isEqualTo("https://test.com/abc?def"); + } + + @Test + public void decodeWxxxFrame_empty() { + byte[] rawId3 = buildSingleFrameTag("WXXX", new byte[0]); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test empty. - rawId3 = buildSingleFrameTag("WXXX", new byte[0]); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(0); + } + + @Test + public void decodeWxxxFrame_encodingByteOnly() { + byte[] rawId3 = buildSingleFrameTag("WXXX", new byte[] {ID3_TEXT_ENCODING_UTF_8}); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test encoding byte only. - rawId3 = buildSingleFrameTag("WXXX", new byte[] {ID3_TEXT_ENCODING_UTF_8}); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); - urlLinkFrame = (UrlLinkFrame) metadata.get(0); + UrlLinkFrame urlLinkFrame = (UrlLinkFrame) metadata.get(0); assertThat(urlLinkFrame.id).isEqualTo("WXXX"); assertThat(urlLinkFrame.description).isEmpty(); assertThat(urlLinkFrame.url).isEmpty(); @@ -210,12 +261,17 @@ public final class Id3DecoderTest { assertThat(urlLinkFrame.id).isEqualTo("WCOM"); assertThat(urlLinkFrame.description).isNull(); assertThat(urlLinkFrame.url).isEqualTo("https://test.com/abc?def"); + } + + @Test + public void decodeUrlLinkFrame_empty() { + byte[] rawId3 = buildSingleFrameTag("WCOM", new byte[0]); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test empty. - rawId3 = buildSingleFrameTag("WCOM", new byte[0]); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); - urlLinkFrame = (UrlLinkFrame) metadata.get(0); + UrlLinkFrame urlLinkFrame = (UrlLinkFrame) metadata.get(0); assertThat(urlLinkFrame.id).isEqualTo("WCOM"); assertThat(urlLinkFrame.description).isNull(); assertThat(urlLinkFrame.url).isEmpty(); @@ -230,12 +286,17 @@ public final class Id3DecoderTest { PrivFrame privFrame = (PrivFrame) metadata.get(0); assertThat(privFrame.owner).isEqualTo("test"); assertThat(privFrame.privateData).isEqualTo(new byte[] {1, 2, 3, 4}); + } + + @Test + public void decodePrivFrame_empty() { + byte[] rawId3 = buildSingleFrameTag("PRIV", new byte[0]); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test empty. - rawId3 = buildSingleFrameTag("PRIV", new byte[0]); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); - privFrame = (PrivFrame) metadata.get(0); + PrivFrame privFrame = (PrivFrame) metadata.get(0); assertThat(privFrame.owner).isEmpty(); assertThat(privFrame.privateData).isEqualTo(new byte[0]); } @@ -258,9 +319,11 @@ public final class Id3DecoderTest { 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}); + } - // Test with UTF-16 description at even offset. - rawId3 = + @Test + public void decodeApicFrame_utf16DescriptionEvenOffset() { + byte[] rawId3 = buildSingleFrameTag( "APIC", new byte[] { @@ -268,28 +331,34 @@ public final class Id3DecoderTest { 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }); - decoder = new Id3Decoder(); - metadata = decoder.decode(rawId3, rawId3.length); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); + assertThat(metadata.length()).isEqualTo(1); - apicFrame = (ApicFrame) metadata.get(0); + ApicFrame apicFrame = (ApicFrame) metadata.get(0); assertThat(apicFrame.mimeType).isEqualTo("image/jpeg"); 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}); + } - // Test with UTF-16 description at odd offset. - rawId3 = + @Test + public void decodeApicFrame_utf16DescriptionOddOffset() { + byte[] rawId3 = buildSingleFrameTag( "APIC", new byte[] { 1, 105, 109, 97, 103, 101, 47, 112, 110, 103, 0, 16, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }); - decoder = new Id3Decoder(); - metadata = decoder.decode(rawId3, rawId3.length); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); + assertThat(metadata.length()).isEqualTo(1); - apicFrame = (ApicFrame) metadata.get(0); + ApicFrame apicFrame = (ApicFrame) metadata.get(0); assertThat(apicFrame.mimeType).isEqualTo("image/png"); assertThat(apicFrame.pictureType).isEqualTo(16); assertThat(apicFrame.description).isEqualTo("Hello World"); @@ -332,17 +401,28 @@ public final class Id3DecoderTest { assertThat(commentFrame.language).isEqualTo("eng"); assertThat(commentFrame.description).isEqualTo("description"); assertThat(commentFrame.text).isEqualTo("text"); + } + + @Test + public void decodeCommentFrame_empty() { + byte[] rawId3 = buildSingleFrameTag("COMM", new byte[0]); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test empty. - rawId3 = buildSingleFrameTag("COMM", new byte[0]); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(0); + } + + @Test + public void decodeCommentFrame_languageOnly() { + byte[] rawId3 = + buildSingleFrameTag("COMM", new byte[] {ID3_TEXT_ENCODING_UTF_8, 101, 110, 103}); + Id3Decoder decoder = new Id3Decoder(); + + Metadata metadata = decoder.decode(rawId3, rawId3.length); - // Test language only. - rawId3 = buildSingleFrameTag("COMM", new byte[] {ID3_TEXT_ENCODING_UTF_8, 101, 110, 103}); - metadata = decoder.decode(rawId3, rawId3.length); assertThat(metadata.length()).isEqualTo(1); - commentFrame = (CommentFrame) metadata.get(0); + CommentFrame commentFrame = (CommentFrame) metadata.get(0); assertThat(commentFrame.language).isEqualTo("eng"); assertThat(commentFrame.description).isEmpty(); assertThat(commentFrame.text).isEmpty(); From 2a0dc414da6df66a036d84e2c0f89411393d87f2 Mon Sep 17 00:00:00 2001 From: kimvde Date: Mon, 28 Nov 2022 11:35:57 +0000 Subject: [PATCH 012/183] Add Transformer internal thread This thread just starts the player and handles the player callbacks for now. Sample pipelines are still run on the playback thread. PiperOrigin-RevId: 491299671 --- .../transformer/ExoPlayerAssetLoader.java | 12 +- .../exoplayer2/transformer/Transformer.java | 21 +- .../transformer/TransformerInternal.java | 245 ++++++++++-------- 3 files changed, 151 insertions(+), 127 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java index 8148c3d1fc..7b2c326aab 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java @@ -63,6 +63,7 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; void onError(Exception e); } + private final MediaItem mediaItem; private final ExoPlayer player; public ExoPlayerAssetLoader( @@ -71,8 +72,10 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; boolean removeAudio, boolean removeVideo, MediaSource.Factory mediaSourceFactory, + Looper looper, Listener listener, Clock clock) { + this.mediaItem = mediaItem; DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); trackSelector.setParameters( new DefaultTrackSelector.Parameters.Builder(context) @@ -92,7 +95,8 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; new ExoPlayer.Builder(context, new RenderersFactoryImpl(removeAudio, removeVideo, listener)) .setMediaSourceFactory(mediaSourceFactory) .setTrackSelector(trackSelector) - .setLoadControl(loadControl); + .setLoadControl(loadControl) + .setLooper(looper); if (clock != Clock.DEFAULT) { // Transformer.Builder#setClock is also @VisibleForTesting, so if we're using a non-default // clock we must be in a test context. @@ -101,11 +105,11 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; } player = playerBuilder.build(); - player.setMediaItem(mediaItem); player.addListener(new PlayerListener(listener)); } public void start() { + player.setMediaItem(mediaItem); player.prepare(); } @@ -113,10 +117,6 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; player.release(); } - public Looper getPlaybackLooper() { - return player.getPlaybackLooper(); - } - private static final class RenderersFactoryImpl implements RenderersFactory { private final TransformerMediaClock mediaClock; 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 10119be2bc..b235833df0 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 @@ -16,12 +16,10 @@ package com.google.android.exoplayer2.transformer; -import static com.google.android.exoplayer2.transformer.TransformerInternal.END_TRANSFORMATION_REASON_CANCELLED; import static com.google.android.exoplayer2.util.Assertions.checkState; import static java.lang.annotation.ElementType.TYPE_USE; import android.content.Context; -import android.os.Handler; import android.os.Looper; import android.os.ParcelFileDescriptor; import androidx.annotation.IntDef; @@ -43,6 +41,7 @@ import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.DebugViewProvider; import com.google.android.exoplayer2.util.Effect; import com.google.android.exoplayer2.util.FrameProcessor; +import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.android.exoplayer2.util.ListenerSet; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; @@ -732,6 +731,7 @@ public final class Transformer { encoderFactory, frameProcessorFactory, muxerFactory, + looper, transformerInternalListener, fallbackListener, debugViewProvider, @@ -778,11 +778,10 @@ public final class Transformer { return; } try { - transformerInternal.release(END_TRANSFORMATION_REASON_CANCELLED); - } catch (TransformationException impossible) { - throw new IllegalStateException(impossible); + transformerInternal.cancel(); + } finally { + transformerInternal = null; } - transformerInternal = null; } private void verifyApplicationThread() { @@ -794,18 +793,17 @@ public final class Transformer { private final class TransformerInternalListener implements TransformerInternal.Listener { private final MediaItem mediaItem; - private final Handler handler; + private final HandlerWrapper handler; public TransformerInternalListener(MediaItem mediaItem) { this.mediaItem = mediaItem; - handler = Util.createHandlerForCurrentLooper(); + handler = clock.createHandler(looper, /* callback= */ null); } @Override public void onTransformationCompleted(TransformationResult transformationResult) { // TODO(b/213341814): Add event flags for Transformer events. - Util.postOrRun( - handler, + handler.post( () -> { transformerInternal = null; listeners.queueEvent( @@ -817,8 +815,7 @@ public final class Transformer { @Override public void onTransformationError(TransformationException exception) { - Util.postOrRun( - handler, + handler.post( () -> { transformerInternal = null; listeners.queueEvent( diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java index a2aa89c219..3d4900eed0 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2.transformer; +import static com.google.android.exoplayer2.transformer.TransformationException.ERROR_CODE_MUXING_FAILED; import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_AVAILABLE; -import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_NO_TRANSFORMATION; import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE; import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_WAITING_FOR_AVAILABILITY; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; @@ -25,7 +25,9 @@ import static java.lang.Math.min; import static java.lang.annotation.ElementType.TYPE_USE; import android.content.Context; -import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; import android.os.ParcelFileDescriptor; import androidx.annotation.IntDef; import androidx.annotation.Nullable; @@ -62,26 +64,24 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } /** - * Represents a reason for ending a transformation. May be one of {@link - * #END_TRANSFORMATION_REASON_COMPLETED}, {@link #END_TRANSFORMATION_REASON_CANCELLED} or {@link - * #END_TRANSFORMATION_REASON_ERROR}. + * Represents a reason for ending a transformation. May be one of {@link #END_REASON_COMPLETED}, + * {@link #END_REASON_CANCELLED} or {@link #END_REASON_ERROR}. */ @Documented @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) - @IntDef({ - END_TRANSFORMATION_REASON_COMPLETED, - END_TRANSFORMATION_REASON_CANCELLED, - END_TRANSFORMATION_REASON_ERROR - }) - public @interface EndTransformationReason {} - + @IntDef({END_REASON_COMPLETED, END_REASON_CANCELLED, END_REASON_ERROR}) + private @interface EndReason {} /** The transformation completed successfully. */ - public static final int END_TRANSFORMATION_REASON_COMPLETED = 0; + private static final int END_REASON_COMPLETED = 0; /** The transformation was cancelled. */ - public static final int END_TRANSFORMATION_REASON_CANCELLED = 1; + private static final int END_REASON_CANCELLED = 1; /** An error occurred during the transformation. */ - public static final int END_TRANSFORMATION_REASON_ERROR = 2; + private static final int END_REASON_ERROR = 2; + + // Internal messages. + private static final int MSG_START = 0; + private static final int MSG_END = 1; private final Context context; private final TransformationRequest transformationRequest; @@ -93,17 +93,18 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private final Listener listener; private final DebugViewProvider debugViewProvider; private final Clock clock; - private final Handler handler; + private final HandlerWrapper applicationHandler; + private final HandlerThread internalHandlerThread; + private final HandlerWrapper internalHandler; private final ExoPlayerAssetLoader exoPlayerAssetLoader; private final MuxerWrapper muxerWrapper; - private final ConditionVariable releasingMuxerConditionVariable; + private final ConditionVariable cancellingConditionVariable; private @Transformer.ProgressState int progressState; private long progressPositionMs; private long durationMs; private boolean released; - private volatile @MonotonicNonNull TransformationResult transformationResult; - private volatile @MonotonicNonNull TransformationException releaseMuxerException; + private @MonotonicNonNull RuntimeException cancelException; public TransformerInternal( Context context, @@ -120,6 +121,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; Codec.EncoderFactory encoderFactory, FrameProcessor.Factory frameProcessorFactory, Muxer.Factory muxerFactory, + Looper applicationLooper, Listener listener, FallbackListener fallbackListener, DebugViewProvider debugViewProvider, @@ -134,14 +136,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; this.listener = listener; this.debugViewProvider = debugViewProvider; this.clock = clock; - handler = Util.createHandlerForCurrentLooper(); + applicationHandler = clock.createHandler(applicationLooper, /* callback= */ null); + internalHandlerThread = new HandlerThread("Transformer:Internal"); + internalHandlerThread.start(); + Looper internalLooper = internalHandlerThread.getLooper(); ComponentListener componentListener = new ComponentListener(mediaItem, fallbackListener); - muxerWrapper = - new MuxerWrapper( - outputPath, - outputParcelFileDescriptor, - muxerFactory, - /* errorConsumer= */ componentListener::onTransformationError); exoPlayerAssetLoader = new ExoPlayerAssetLoader( context, @@ -149,14 +148,26 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; removeAudio, removeVideo, mediaSourceFactory, + internalLooper, componentListener, clock); - releasingMuxerConditionVariable = new ConditionVariable(); + muxerWrapper = + new MuxerWrapper( + outputPath, + outputParcelFileDescriptor, + muxerFactory, + /* errorConsumer= */ componentListener::onTransformationError); + cancellingConditionVariable = new ConditionVariable(); progressState = PROGRESS_STATE_WAITING_FOR_AVAILABILITY; + // It's safe to use "this" because we don't send a message before exiting the constructor. + @SuppressWarnings("nullness:methodref.receiver.bound") + HandlerWrapper internalHandler = + clock.createHandler(internalLooper, /* callback= */ this::handleMessage); + this.internalHandler = internalHandler; } public void start() { - exoPlayerAssetLoader.start(); + internalHandler.sendEmptyMessage(MSG_START); } public @Transformer.ProgressState int getProgress(ProgressHolder progressHolder) { @@ -166,26 +177,53 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; return progressState; } - /** - * Releases the resources. - * - * @param endTransformationReason The {@linkplain EndTransformationReason reason} for ending the - * transformation. - * @throws TransformationException If the muxer is in the wrong state and {@code - * endTransformationReason} is not {@link #END_TRANSFORMATION_REASON_CANCELLED}. - */ - public void release(@EndTransformationReason int endTransformationReason) - throws TransformationException { - if (released) { - return; + public void cancel() { + internalHandler + .obtainMessage( + MSG_END, END_REASON_CANCELLED, /* unused */ 0, /* transformationException */ null) + .sendToTarget(); + clock.onThreadBlocked(); + cancellingConditionVariable.blockUninterruptible(); + if (cancelException != null) { + throw cancelException; } - progressState = PROGRESS_STATE_NO_TRANSFORMATION; - released = true; - HandlerWrapper playbackHandler = - clock.createHandler(exoPlayerAssetLoader.getPlaybackLooper(), /* callback= */ null); - playbackHandler.post( - () -> { - if (endTransformationReason == END_TRANSFORMATION_REASON_COMPLETED) { + } + + private boolean handleMessage(Message msg) { + try { + switch (msg.what) { + case MSG_START: + startInternal(); + break; + case MSG_END: + endInternal( + /* endReason= */ msg.arg1, + /* transformationException= */ (TransformationException) msg.obj); + break; + default: + return false; + } + } catch (RuntimeException e) { + endInternal(END_REASON_ERROR, TransformationException.createForUnexpected(e)); + } + return true; + } + + private void startInternal() { + exoPlayerAssetLoader.start(); + } + + private void endInternal( + @EndReason int endReason, @Nullable TransformationException transformationException) { + @Nullable TransformationResult transformationResult = null; + boolean forCancellation = endReason == END_REASON_CANCELLED; + @Nullable TransformationException releaseTransformationException = null; + if (!released) { + released = true; + try { + try { + exoPlayerAssetLoader.release(); + if (endReason == END_REASON_COMPLETED) { transformationResult = new TransformationResult.Builder() .setDurationMs(checkNotNull(muxerWrapper).getDurationMs()) @@ -195,24 +233,37 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; .setFileSizeBytes(muxerWrapper.getCurrentOutputSizeBytes()) .build(); } - try { - muxerWrapper.release( - /* forCancellation= */ endTransformationReason - == END_TRANSFORMATION_REASON_CANCELLED); - } catch (Muxer.MuxerException e) { - releaseMuxerException = - TransformationException.createForMuxer( - e, TransformationException.ERROR_CODE_MUXING_FAILED); - } finally { - releasingMuxerConditionVariable.open(); - } - }); - clock.onThreadBlocked(); - releasingMuxerConditionVariable.blockUninterruptible(); - exoPlayerAssetLoader.release(); - if (releaseMuxerException != null) { - throw releaseMuxerException; + } finally { + muxerWrapper.release(forCancellation); + } + } catch (Muxer.MuxerException e) { + releaseTransformationException = + TransformationException.createForMuxer(e, ERROR_CODE_MUXING_FAILED); + } catch (RuntimeException e) { + releaseTransformationException = TransformationException.createForUnexpected(e); + cancelException = e; + } } + + if (!forCancellation) { + TransformationException exception = transformationException; + if (exception == null) { + // We only report the exception caused by releasing the resources if there is no other + // exception. It is more intuitive to call the error callback only once and reporting the + // exception caused by releasing the resources can be confusing if it is a consequence of + // the first exception. + exception = releaseTransformationException; + } + + if (exception != null) { + listener.onTransformationError(exception); + } else { + listener.onTransformationCompleted(checkNotNull(transformationResult)); + } + } + + internalHandlerThread.quitSafely(); + cancellingConditionVariable.open(); } private class ComponentListener @@ -236,14 +287,17 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override public void onDurationMs(long durationMs) { - // Make progress permanently unavailable if the duration is unknown, so that it doesn't jump - // to a high value at the end of the transformation if the duration is set once the media is - // entirely loaded. - progressState = - durationMs <= 0 || durationMs == C.TIME_UNSET - ? PROGRESS_STATE_UNAVAILABLE - : PROGRESS_STATE_AVAILABLE; - TransformerInternal.this.durationMs = durationMs; + applicationHandler.post( + () -> { + // Make progress permanently unavailable if the duration is unknown, so that it doesn't + // jump to a high value at the end of the transformation if the duration is set once the + // media is entirely loaded. + progressState = + durationMs <= 0 || durationMs == C.TIME_UNSET + ? PROGRESS_STATE_UNAVAILABLE + : PROGRESS_STATE_AVAILABLE; + TransformerInternal.this.durationMs = durationMs; + }); } @Override @@ -278,12 +332,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } else { transformationException = TransformationException.createForUnexpected(e); } - handleTransformationEnded(transformationException); + onTransformationError(transformationException); } @Override public void onEnded() { - handleTransformationEnded(/* transformationException= */ null); + internalHandler + .obtainMessage( + MSG_END, END_REASON_COMPLETED, /* unused */ 0, /* transformationException */ null) + .sendToTarget(); } // SamplePipeline.Listener implementation. @@ -295,15 +352,17 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; if (elapsedTimeMs > lastProgressUpdateMs + MIN_DURATION_BETWEEN_PROGRESS_UPDATES_MS && positionMs > lastProgressPositionMs) { lastProgressUpdateMs = elapsedTimeMs; - // Store positionMs in a local variable to make sure the thread reads the latest value. + // Store positionMs in a variable to make sure the thread reads the latest value. lastProgressPositionMs = positionMs; - handler.post(() -> progressPositionMs = positionMs); + applicationHandler.post(() -> progressPositionMs = positionMs); } } @Override public void onTransformationError(TransformationException transformationException) { - handleTransformationEnded(transformationException); + internalHandler + .obtainMessage(MSG_END, END_REASON_ERROR, /* unused */ 0, transformationException) + .sendToTarget(); } private SamplePipeline getSamplePipeline( @@ -427,37 +486,5 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } return false; } - - private void handleTransformationEnded( - @Nullable TransformationException transformationException) { - handler.post( - () -> { - @Nullable TransformationException releaseException = null; - try { - release( - transformationException == null - ? END_TRANSFORMATION_REASON_COMPLETED - : END_TRANSFORMATION_REASON_ERROR); - } catch (TransformationException e) { - releaseException = e; - } catch (RuntimeException e) { - releaseException = TransformationException.createForUnexpected(e); - } - TransformationException exception = transformationException; - if (exception == null) { - // We only report the exception caused by releasing the resources if there is no other - // exception. It is more intuitive to call the error callback only once and reporting - // the exception caused by releasing the resources can be confusing if it is a - // consequence of the first exception. - exception = releaseException; - } - - if (exception != null) { - listener.onTransformationError(exception); - } else { - listener.onTransformationCompleted(checkNotNull(transformationResult)); - } - }); - } } } From 39f01bfb93738ff4f3c14702f311e31bffcb88cd Mon Sep 17 00:00:00 2001 From: huangdarwin Date: Mon, 28 Nov 2022 14:07:59 +0000 Subject: [PATCH 013/183] HDR: Apply OETF in HDR external sampler GLSL shader. This should fix how color matrix transforms look when applied on HDR colors PiperOrigin-RevId: 491323228 --- .../shaders/fragment_shader_oetf_es3.glsl | 19 ++-- ...hader_transformation_external_yuv_es3.glsl | 88 ++++++++++++++++--- .../effect/MatrixTextureProcessor.java | 11 ++- 3 files changed, 92 insertions(+), 26 deletions(-) diff --git a/library/effect/src/main/assets/shaders/fragment_shader_oetf_es3.glsl b/library/effect/src/main/assets/shaders/fragment_shader_oetf_es3.glsl index 31dd05b80a..fe56dc8ee5 100644 --- a/library/effect/src/main/assets/shaders/fragment_shader_oetf_es3.glsl +++ b/library/effect/src/main/assets/shaders/fragment_shader_oetf_es3.glsl @@ -14,12 +14,13 @@ // limitations under the License. // ES 3 fragment shader that: -// 1. samples optical linear BT.2020 RGB from a (non-external) texture with -// uTexSampler, and applies a 4x4 RGB color matrix to change the pixel -// colors, -// 2. applies the HLG or PQ OETF to yield electrical (HLG or PQ) BT.2020 RGB, -// and -// 3. copies this converted texture color to the current output. +// 1. Samples optical linear BT.2020 RGB from a (non-external) texture with +// uTexSampler. +// 2. Applies a 4x4 RGB color matrix to change the pixel colors. +// 3. Applies the HLG or PQ OETF to yield electrical (HLG or PQ) BT.2020 RGB, +// based on uOetfColorTransfer. +// 4. Copies this converted texture color to the current output. +// The output will be red if an error has occurred. precision mediump float; uniform sampler2D uTexSampler; @@ -75,8 +76,8 @@ highp vec3 pqOetf(highp vec3 linearColor) { } // Applies the appropriate OETF to convert linear optical signals to nonlinear -// electrical signals. Input and output are both normalzied to [0, 1]. -highp vec3 getElectricalColor(highp vec3 linearColor) { +// electrical signals. Input and output are both normalized to [0, 1]. +highp vec3 applyOetf(highp vec3 linearColor) { // LINT.IfChange(color_transfer) const int COLOR_TRANSFER_ST2084 = 6; const int COLOR_TRANSFER_HLG = 7; @@ -94,5 +95,5 @@ void main() { vec4 inputColor = texture(uTexSampler, vTexSamplingCoord); // transformedColors is an optical color. vec4 transformedColors = uRgbMatrix * vec4(inputColor.rgb, 1); - outColor = vec4(getElectricalColor(transformedColors.rgb), inputColor.a); + outColor = vec4(applyOetf(transformedColors.rgb), inputColor.a); } diff --git a/library/effect/src/main/assets/shaders/fragment_shader_transformation_external_yuv_es3.glsl b/library/effect/src/main/assets/shaders/fragment_shader_transformation_external_yuv_es3.glsl index f06e6967e1..aaabf57ac4 100644 --- a/library/effect/src/main/assets/shaders/fragment_shader_transformation_external_yuv_es3.glsl +++ b/library/effect/src/main/assets/shaders/fragment_shader_transformation_external_yuv_es3.glsl @@ -20,11 +20,13 @@ // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_YUV_target.txt, // 2. Applies a YUV to RGB conversion using the specified color transform // uYuvToRgbColorTransform, yielding electrical (HLG or PQ) BT.2020 RGB, -// 3. If uEotfColorTransfer is COLOR_TRANSFER_NO_VALUE, outputs electrical -// (HLG or PQ) BT.2020 RGB. Otherwise, outputs optical linear BT.2020 RGB for -// intermediate shaders by applying the HLG or PQ EOTF. -// 4. Copies this converted texture color to the current output, with alpha = 1, -// while applying a 4x4 RGB color matrix to change the pixel colors. +// 3. Applies an EOTF based on uEotfColorTransfer, yielding optical linear +// BT.2020 RGB. +// 4. Applies a 4x4 RGB color matrix to change the pixel colors. +// 5. If uOetfColorTransfer is COLOR_TRANSFER_LINEAR, outputs linear colors as +// is to intermediate shaders. Otherwise, applies the HLG or PQ OETF, based +// on uOetfColorTransfer, to provide the corresponding output electrical color. +// The output will be red if an error has occurred. #extension GL_OES_EGL_image_external : require #extension GL_EXT_YUV_target : require @@ -33,7 +35,12 @@ uniform __samplerExternal2DY2YEXT uTexSampler; uniform mat3 uYuvToRgbColorTransform; uniform mat4 uRgbMatrix; // C.java#ColorTransfer value. +// Only COLOR_TRANSFER_ST2084 and COLOR_TRANSFER_HLG are allowed. uniform int uEotfColorTransfer; +// C.java#ColorTransfer value. +// Only COLOR_TRANSFER_LINEAR, COLOR_TRANSFER_ST2084, and COLOR_TRANSFER_HLG are +// allowed. +uniform int uOetfColorTransfer; in vec2 vTexSamplingCoord; out vec4 outColor; @@ -81,19 +88,74 @@ highp vec3 pqEotf(highp vec3 pqColor) { // Applies the appropriate EOTF to convert nonlinear electrical values to linear // optical values. Input and output are both normalized to [0, 1]. -highp vec3 getOpticalColor(highp vec3 electricalColor) { +highp vec3 applyEotf(highp vec3 electricalColor) { // LINT.IfChange(color_transfer) const int COLOR_TRANSFER_ST2084 = 6; const int COLOR_TRANSFER_HLG = 7; - const int FORMAT_NO_VALUE = -1; - if (uEotfColorTransfer == COLOR_TRANSFER_ST2084) { return pqEotf(electricalColor); } else if (uEotfColorTransfer == COLOR_TRANSFER_HLG) { return hlgEotf(electricalColor); - } else if (uEotfColorTransfer == FORMAT_NO_VALUE) { - return electricalColor; + } else { + // Output red as an obviously visible error. + return vec3(1.0, 0.0, 0.0); + } +} + +// HLG OETF for one channel. +highp float hlgOetfSingleChannel(highp float linearChannel) { + // Specification: + // https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.inline.html#TRANSFER_HLG + // Reference implementation: + // https://cs.android.com/android/platform/superproject/+/master:frameworks/native/libs/renderengine/gl/ProgramCache.cpp;l=529-543;drc=de09f10aa504fd8066370591a00c9ff1cafbb7fa + const highp float a = 0.17883277; + const highp float b = 0.28466892; + const highp float c = 0.55991073; + + return linearChannel <= 1.0 / 12.0 ? sqrt(3.0 * linearChannel) : + a * log(12.0 * linearChannel - b) + c; +} + +// BT.2100 / BT.2020 HLG OETF. +highp vec3 hlgOetf(highp vec3 linearColor) { + return vec3( + hlgOetfSingleChannel(linearColor.r), + hlgOetfSingleChannel(linearColor.g), + hlgOetfSingleChannel(linearColor.b) + ); +} + +// BT.2100 / BT.2020, PQ / ST2084 OETF. +highp vec3 pqOetf(highp vec3 linearColor) { + // Specification: + // https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.inline.html#TRANSFER_PQ + // Reference implementation: + // https://cs.android.com/android/platform/superproject/+/master:frameworks/native/libs/renderengine/gl/ProgramCache.cpp;l=514-527;drc=de09f10aa504fd8066370591a00c9ff1cafbb7fa + const highp float m1 = (2610.0 / 16384.0); + const highp float m2 = (2523.0 / 4096.0) * 128.0; + const highp float c1 = (3424.0 / 4096.0); + const highp float c2 = (2413.0 / 4096.0) * 32.0; + const highp float c3 = (2392.0 / 4096.0) * 32.0; + + highp vec3 temp = pow(linearColor, vec3(m1)); + temp = (c1 + c2 * temp) / (1.0 + c3 * temp); + return pow(temp, vec3(m2)); +} + +// Applies the appropriate OETF to convert linear optical signals to nonlinear +// electrical signals. Input and output are both normalized to [0, 1]. +highp vec3 applyOetf(highp vec3 linearColor) { + // LINT.IfChange(color_transfer_oetf) + const int COLOR_TRANSFER_LINEAR = 1; + const int COLOR_TRANSFER_ST2084 = 6; + const int COLOR_TRANSFER_HLG = 7; + if(uOetfColorTransfer == COLOR_TRANSFER_ST2084) { + return pqOetf(linearColor); + } else if(uOetfColorTransfer == COLOR_TRANSFER_HLG) { + return hlgOetf(linearColor); + } else if (uOetfColorTransfer == COLOR_TRANSFER_LINEAR) { + return linearColor; } else { // Output red as an obviously visible error. return vec3(1.0, 0.0, 0.0); @@ -107,7 +169,7 @@ vec3 yuvToRgb(vec3 yuv) { void main() { vec3 srcYuv = texture(uTexSampler, vTexSamplingCoord).xyz; - vec3 rgb = yuvToRgb(srcYuv); - outColor = uRgbMatrix * vec4(getOpticalColor(rgb), 1.0); - // TODO(b/241902517): Transform optical to electrical colors. + vec4 opticalColor = vec4(applyEotf(yuvToRgb(srcYuv)), 1.0); + vec4 transformedColors = uRgbMatrix * opticalColor; + outColor = vec4(applyOetf(transformedColors.rgb), 1.0); } diff --git a/library/effect/src/main/java/com/google/android/exoplayer2/effect/MatrixTextureProcessor.java b/library/effect/src/main/java/com/google/android/exoplayer2/effect/MatrixTextureProcessor.java index 673767e63c..f48c017a7c 100644 --- a/library/effect/src/main/java/com/google/android/exoplayer2/effect/MatrixTextureProcessor.java +++ b/library/effect/src/main/java/com/google/android/exoplayer2/effect/MatrixTextureProcessor.java @@ -23,7 +23,6 @@ import android.opengl.GLES20; import android.opengl.Matrix; import android.util.Pair; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.FrameProcessingException; import com.google.android.exoplayer2.util.GlProgram; import com.google.android.exoplayer2.util.GlUtil; @@ -152,7 +151,6 @@ import java.util.List; context, VERTEX_SHADER_TRANSFORMATION_PATH, FRAGMENT_SHADER_TRANSFORMATION_PATH); // No transfer functions needed, because input and output are both optical colors. - // TODO(b/241902517): Add transfer functions since existing color filters may change the colors. return new MatrixTextureProcessor( glProgram, ImmutableList.copyOf(matrixTransformations), @@ -214,6 +212,8 @@ import java.util.List; checkArgument( colorTransfer == C.COLOR_TRANSFER_HLG || colorTransfer == C.COLOR_TRANSFER_ST2084); glProgram.setIntUniform("uEotfColorTransfer", colorTransfer); + // No OETF needed, because the intended output here is optical colors. + glProgram.setIntUniform("uOetfColorTransfer", C.COLOR_TRANSFER_LINEAR); } else { glProgram.setIntUniform("uApplyOetf", 0); } @@ -317,8 +317,11 @@ import java.util.List; ? BT2020_FULL_RANGE_YUV_TO_RGB_COLOR_TRANSFORM_MATRIX : BT2020_LIMITED_RANGE_YUV_TO_RGB_COLOR_TRANSFORM_MATRIX); - // No transfer functions needed, because the EOTF and OETF cancel out. - glProgram.setIntUniform("uEotfColorTransfer", Format.NO_VALUE); + @C.ColorTransfer int colorTransfer = electricalColorInfo.colorTransfer; + checkArgument( + colorTransfer == C.COLOR_TRANSFER_HLG || colorTransfer == C.COLOR_TRANSFER_ST2084); + glProgram.setIntUniform("uEotfColorTransfer", colorTransfer); + glProgram.setIntUniform("uOetfColorTransfer", colorTransfer); } else { glProgram.setIntUniform("uApplyOetf", 1); } From 043546a03475356764cf8b754bd0fff87a0c6e1a Mon Sep 17 00:00:00 2001 From: ibaker Date: Mon, 28 Nov 2022 14:15:03 +0000 Subject: [PATCH 014/183] Remove impossible `UnsupportedEncodingException` from `Id3Decoder` The list of charsets is already hard-coded, and using `Charset` types ensures they will all be present at run-time, hence we will never encounter an 'unsupported' charset. PiperOrigin-RevId: 491324466 --- .../exoplayer2/metadata/id3/Id3Decoder.java | 104 ++++++++---------- 1 file changed, 46 insertions(+), 58 deletions(-) diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java b/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java index ccf9f2f715..0ee41664e4 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java @@ -25,9 +25,10 @@ import com.google.android.exoplayer2.util.ParsableBitArray; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; import com.google.common.base.Ascii; +import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -434,30 +435,25 @@ public final class Id3Decoder extends SimpleMetadataDecoder { + frameSize); } return frame; - } catch (UnsupportedEncodingException e) { - Log.w(TAG, "Unsupported character encoding"); - return null; } finally { id3Data.setPosition(nextFramePosition); } } @Nullable - private static TextInformationFrame decodeTxxxFrame(ParsableByteArray id3Data, int frameSize) - throws UnsupportedEncodingException { + private static TextInformationFrame decodeTxxxFrame(ParsableByteArray id3Data, int frameSize) { if (frameSize < 1) { // Frame is malformed. return null; } int encoding = id3Data.readUnsignedByte(); - String charset = getCharsetName(encoding); byte[] data = new byte[frameSize - 1]; id3Data.readBytes(data, 0, frameSize - 1); int descriptionEndIndex = indexOfTerminator(data, 0, encoding); - String description = new String(data, 0, descriptionEndIndex, charset); + String description = new String(data, 0, descriptionEndIndex, getCharset(encoding)); ImmutableList values = decodeTextInformationFrameValues( @@ -467,7 +463,7 @@ public final class Id3Decoder extends SimpleMetadataDecoder { @Nullable private static TextInformationFrame decodeTextInformationFrame( - ParsableByteArray id3Data, int frameSize, String id) throws UnsupportedEncodingException { + ParsableByteArray id3Data, int frameSize, String id) { if (frameSize < 1) { // Frame is malformed. return null; @@ -483,17 +479,17 @@ public final class Id3Decoder extends SimpleMetadataDecoder { } private static ImmutableList decodeTextInformationFrameValues( - byte[] data, final int encoding, final int index) throws UnsupportedEncodingException { + byte[] data, final int encoding, final int index) { if (index >= data.length) { return ImmutableList.of(""); } ImmutableList.Builder values = ImmutableList.builder(); - String charset = getCharsetName(encoding); int valueStartIndex = index; int valueEndIndex = indexOfTerminator(data, valueStartIndex, encoding); while (valueStartIndex < valueEndIndex) { - String value = new String(data, valueStartIndex, valueEndIndex - valueStartIndex, charset); + String value = + new String(data, valueStartIndex, valueEndIndex - valueStartIndex, getCharset(encoding)); values.add(value); valueStartIndex = valueEndIndex + delimiterLength(encoding); @@ -505,47 +501,44 @@ public final class Id3Decoder extends SimpleMetadataDecoder { } @Nullable - private static UrlLinkFrame decodeWxxxFrame(ParsableByteArray id3Data, int frameSize) - throws UnsupportedEncodingException { + private static UrlLinkFrame decodeWxxxFrame(ParsableByteArray id3Data, int frameSize) { if (frameSize < 1) { // Frame is malformed. return null; } int encoding = id3Data.readUnsignedByte(); - String charset = getCharsetName(encoding); byte[] data = new byte[frameSize - 1]; id3Data.readBytes(data, 0, frameSize - 1); int descriptionEndIndex = indexOfTerminator(data, 0, encoding); - String description = new String(data, 0, descriptionEndIndex, charset); + String description = new String(data, 0, descriptionEndIndex, getCharset(encoding)); int urlStartIndex = descriptionEndIndex + delimiterLength(encoding); int urlEndIndex = indexOfZeroByte(data, urlStartIndex); - String url = decodeStringIfValid(data, urlStartIndex, urlEndIndex, "ISO-8859-1"); + String url = decodeStringIfValid(data, urlStartIndex, urlEndIndex, Charsets.ISO_8859_1); return new UrlLinkFrame("WXXX", description, url); } private static UrlLinkFrame decodeUrlLinkFrame( - ParsableByteArray id3Data, int frameSize, String id) throws UnsupportedEncodingException { + ParsableByteArray id3Data, int frameSize, String id) { byte[] data = new byte[frameSize]; id3Data.readBytes(data, 0, frameSize); int urlEndIndex = indexOfZeroByte(data, 0); - String url = new String(data, 0, urlEndIndex, "ISO-8859-1"); + String url = new String(data, 0, urlEndIndex, Charsets.ISO_8859_1); return new UrlLinkFrame(id, null, url); } - private static PrivFrame decodePrivFrame(ParsableByteArray id3Data, int frameSize) - throws UnsupportedEncodingException { + private static PrivFrame decodePrivFrame(ParsableByteArray id3Data, int frameSize) { byte[] data = new byte[frameSize]; id3Data.readBytes(data, 0, frameSize); int ownerEndIndex = indexOfZeroByte(data, 0); - String owner = new String(data, 0, ownerEndIndex, "ISO-8859-1"); + String owner = new String(data, 0, ownerEndIndex, Charsets.ISO_8859_1); int privateDataStartIndex = ownerEndIndex + 1; byte[] privateData = copyOfRangeIfValid(data, privateDataStartIndex, data.length); @@ -553,16 +546,15 @@ public final class Id3Decoder extends SimpleMetadataDecoder { return new PrivFrame(owner, privateData); } - private static GeobFrame decodeGeobFrame(ParsableByteArray id3Data, int frameSize) - throws UnsupportedEncodingException { + private static GeobFrame decodeGeobFrame(ParsableByteArray id3Data, int frameSize) { int encoding = id3Data.readUnsignedByte(); - String charset = getCharsetName(encoding); + Charset charset = getCharset(encoding); byte[] data = new byte[frameSize - 1]; id3Data.readBytes(data, 0, frameSize - 1); int mimeTypeEndIndex = indexOfZeroByte(data, 0); - String mimeType = new String(data, 0, mimeTypeEndIndex, "ISO-8859-1"); + String mimeType = new String(data, 0, mimeTypeEndIndex, Charsets.ISO_8859_1); int filenameStartIndex = mimeTypeEndIndex + 1; int filenameEndIndex = indexOfTerminator(data, filenameStartIndex, encoding); @@ -580,10 +572,9 @@ public final class Id3Decoder extends SimpleMetadataDecoder { } private static ApicFrame decodeApicFrame( - ParsableByteArray id3Data, int frameSize, int majorVersion) - throws UnsupportedEncodingException { + ParsableByteArray id3Data, int frameSize, int majorVersion) { int encoding = id3Data.readUnsignedByte(); - String charset = getCharsetName(encoding); + Charset charset = getCharset(encoding); byte[] data = new byte[frameSize - 1]; id3Data.readBytes(data, 0, frameSize - 1); @@ -592,13 +583,13 @@ public final class Id3Decoder extends SimpleMetadataDecoder { int mimeTypeEndIndex; if (majorVersion == 2) { mimeTypeEndIndex = 2; - mimeType = "image/" + Ascii.toLowerCase(new String(data, 0, 3, "ISO-8859-1")); + mimeType = "image/" + Ascii.toLowerCase(new String(data, 0, 3, Charsets.ISO_8859_1)); if ("image/jpg".equals(mimeType)) { mimeType = "image/jpeg"; } } else { mimeTypeEndIndex = indexOfZeroByte(data, 0); - mimeType = Ascii.toLowerCase(new String(data, 0, mimeTypeEndIndex, "ISO-8859-1")); + mimeType = Ascii.toLowerCase(new String(data, 0, mimeTypeEndIndex, Charsets.ISO_8859_1)); if (mimeType.indexOf('/') == -1) { mimeType = "image/" + mimeType; } @@ -619,15 +610,14 @@ public final class Id3Decoder extends SimpleMetadataDecoder { } @Nullable - private static CommentFrame decodeCommentFrame(ParsableByteArray id3Data, int frameSize) - throws UnsupportedEncodingException { + private static CommentFrame decodeCommentFrame(ParsableByteArray id3Data, int frameSize) { if (frameSize < 4) { // Frame is malformed. return null; } int encoding = id3Data.readUnsignedByte(); - String charset = getCharsetName(encoding); + Charset charset = getCharset(encoding); byte[] data = new byte[3]; id3Data.readBytes(data, 0, 3); @@ -652,13 +642,15 @@ public final class Id3Decoder extends SimpleMetadataDecoder { int majorVersion, boolean unsignedIntFrameSizeHack, int frameHeaderSize, - @Nullable FramePredicate framePredicate) - throws UnsupportedEncodingException { + @Nullable FramePredicate framePredicate) { int framePosition = id3Data.getPosition(); int chapterIdEndIndex = indexOfZeroByte(id3Data.getData(), framePosition); String chapterId = new String( - id3Data.getData(), framePosition, chapterIdEndIndex - framePosition, "ISO-8859-1"); + id3Data.getData(), + framePosition, + chapterIdEndIndex - framePosition, + Charsets.ISO_8859_1); id3Data.setPosition(chapterIdEndIndex + 1); int startTime = id3Data.readInt(); @@ -693,13 +685,15 @@ public final class Id3Decoder extends SimpleMetadataDecoder { int majorVersion, boolean unsignedIntFrameSizeHack, int frameHeaderSize, - @Nullable FramePredicate framePredicate) - throws UnsupportedEncodingException { + @Nullable FramePredicate framePredicate) { int framePosition = id3Data.getPosition(); int elementIdEndIndex = indexOfZeroByte(id3Data.getData(), framePosition); String elementId = new String( - id3Data.getData(), framePosition, elementIdEndIndex - framePosition, "ISO-8859-1"); + id3Data.getData(), + framePosition, + elementIdEndIndex - framePosition, + Charsets.ISO_8859_1); id3Data.setPosition(elementIdEndIndex + 1); int ctocFlags = id3Data.readUnsignedByte(); @@ -711,7 +705,8 @@ public final class Id3Decoder extends SimpleMetadataDecoder { for (int i = 0; i < childCount; i++) { int startIndex = id3Data.getPosition(); int endIndex = indexOfZeroByte(id3Data.getData(), startIndex); - children[i] = new String(id3Data.getData(), startIndex, endIndex - startIndex, "ISO-8859-1"); + children[i] = + new String(id3Data.getData(), startIndex, endIndex - startIndex, Charsets.ISO_8859_1); id3Data.setPosition(endIndex + 1); } @@ -790,23 +785,18 @@ public final class Id3Decoder extends SimpleMetadataDecoder { return length; } - /** - * Maps encoding byte from ID3v2 frame to a Charset. - * - * @param encodingByte The value of encoding byte from ID3v2 frame. - * @return Charset name. - */ - private static String getCharsetName(int encodingByte) { + /** Maps encoding byte from ID3v2 frame to a {@link Charset}. */ + private static Charset getCharset(int encodingByte) { switch (encodingByte) { case ID3_TEXT_ENCODING_UTF_16: - return "UTF-16"; + return Charsets.UTF_16; case ID3_TEXT_ENCODING_UTF_16BE: - return "UTF-16BE"; + return Charsets.UTF_16BE; case ID3_TEXT_ENCODING_UTF_8: - return "UTF-8"; + return Charsets.UTF_8; case ID3_TEXT_ENCODING_ISO_8859_1: default: - return "ISO-8859-1"; + return Charsets.ISO_8859_1; } } @@ -869,21 +859,19 @@ public final class Id3Decoder extends SimpleMetadataDecoder { /** * Returns a string obtained by decoding the specified range of {@code data} using the specified - * {@code charsetName}. An empty string is returned if the range is invalid. + * {@code charset}. An empty string is returned if the range is invalid. * * @param data The array from which to decode the string. * @param from The start of the range. * @param to The end of the range (exclusive). - * @param charsetName The name of the Charset to use. + * @param charset The {@link Charset} to use. * @return The decoded string, or an empty string if the range is invalid. - * @throws UnsupportedEncodingException If the Charset is not supported. */ - private static String decodeStringIfValid(byte[] data, int from, int to, String charsetName) - throws UnsupportedEncodingException { + private static String decodeStringIfValid(byte[] data, int from, int to, Charset charset) { if (to <= from || to > data.length) { return ""; } - return new String(data, from, to - from, charsetName); + return new String(data, from, to - from, charset); } private static final class Id3Header { From 51d1c0b892474b91ddd5e2eb6278bd86c5500fe7 Mon Sep 17 00:00:00 2001 From: claincly Date: Mon, 28 Nov 2022 18:16:19 +0000 Subject: [PATCH 015/183] Fix VideoEncoderSetting.bitrate is ignored when set PiperOrigin-RevId: 491377695 --- .../transformer/DefaultEncoderFactory.java | 116 ++++++++++++------ .../DefaultEncoderFactoryTest.java | 90 ++++++++++++++ 2 files changed, 169 insertions(+), 37 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java index 2a98683829..24480ebe13 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java @@ -204,6 +204,25 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { /* outputSurface= */ null); } + /** + * Returns a {@link DefaultCodec} for video encoding. + * + *

Use {@link Builder#setRequestedVideoEncoderSettings} with {@link + * VideoEncoderSettings#bitrate} set to request for a specific encoding bitrate. Bitrate settings + * in {@link Format} are ignored when {@link VideoEncoderSettings#bitrate} or {@link + * VideoEncoderSettings#enableHighQualityTargeting} is set. + * + * @param format The {@link Format} (of the output data) used to determine the underlying encoder + * and its configuration values. {@link Format#sampleMimeType}, {@link Format#width} and + * {@link Format#height} are set to those of the desired output video format. {@link + * Format#rotationDegrees} is 0 and {@link Format#width} {@code >=} {@link Format#height}, + * therefore the video is always in landscape orientation. {@link Format#frameRate} is set to + * the output video's frame rate, if available. + * @param allowedMimeTypes The non-empty list of allowed output sample {@linkplain MimeTypes MIME + * types}. + * @return A {@link DefaultCodec} for video encoding. + * @throws TransformationException If no suitable {@link DefaultCodec} can be created. + */ @Override public Codec createForVideoEncoding(Format format, List allowedMimeTypes) throws TransformationException { @@ -244,26 +263,35 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { mimeType, encoderSupportedFormat.width, encoderSupportedFormat.height); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, round(encoderSupportedFormat.frameRate)); - if (supportedVideoEncoderSettings.enableHighQualityTargeting) { - int bitrate = - new DeviceMappedEncoderBitrateProvider() - .getBitrate( - encoderInfo.getName(), - encoderSupportedFormat.width, - encoderSupportedFormat.height, - encoderSupportedFormat.frameRate); - encoderSupportedFormat = - encoderSupportedFormat.buildUpon().setAverageBitrate(bitrate).build(); - } else if (encoderSupportedFormat.bitrate == Format.NO_VALUE) { - int bitrate = - getSuggestedBitrate( - encoderSupportedFormat.width, - encoderSupportedFormat.height, - encoderSupportedFormat.frameRate); - encoderSupportedFormat = - encoderSupportedFormat.buildUpon().setAverageBitrate(bitrate).build(); + int finalBitrate; + if (enableFallback) { + finalBitrate = supportedVideoEncoderSettings.bitrate; + } else { + // supportedVideoEncoderSettings is identical to requestedVideoEncoderSettings. + if (supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE) { + finalBitrate = supportedVideoEncoderSettings.bitrate; + } else if (supportedVideoEncoderSettings.enableHighQualityTargeting) { + finalBitrate = + new DeviceMappedEncoderBitrateProvider() + .getBitrate( + encoderInfo.getName(), + encoderSupportedFormat.width, + encoderSupportedFormat.height, + encoderSupportedFormat.frameRate); + } else if (encoderSupportedFormat.averageBitrate != Format.NO_VALUE) { + finalBitrate = encoderSupportedFormat.averageBitrate; + } else { + finalBitrate = + getSuggestedBitrate( + encoderSupportedFormat.width, + encoderSupportedFormat.height, + encoderSupportedFormat.frameRate); + } } + encoderSupportedFormat = + encoderSupportedFormat.buildUpon().setAverageBitrate(finalBitrate).build(); + mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, encoderSupportedFormat.averageBitrate); mediaFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, supportedVideoEncoderSettings.bitrateMode); @@ -387,16 +415,23 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { requestedFormat.width, requestedFormat.height)); - int requestedBitrate = - videoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE - ? videoEncoderSettings.bitrate - : getSuggestedBitrate( - finalResolution.getWidth(), finalResolution.getHeight(), requestedFormat.frameRate); - - filteredEncoderInfos = - filterEncodersByBitrate(filteredEncoderInfos, mimeType, requestedBitrate); - if (filteredEncoderInfos.isEmpty()) { - return null; + int requestedBitrate = Format.NO_VALUE; + // Encoders are not filtered by bitrate if high quality targeting is enabled. + if (!videoEncoderSettings.enableHighQualityTargeting) { + requestedBitrate = + videoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE + ? videoEncoderSettings.bitrate + : requestedFormat.averageBitrate != Format.NO_VALUE + ? requestedFormat.averageBitrate + : getSuggestedBitrate( + finalResolution.getWidth(), + finalResolution.getHeight(), + requestedFormat.frameRate); + filteredEncoderInfos = + filterEncodersByBitrate(filteredEncoderInfos, mimeType, requestedBitrate); + if (filteredEncoderInfos.isEmpty()) { + return null; + } } filteredEncoderInfos = @@ -406,11 +441,6 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { return null; } - // TODO(b/238094555): Check encoder supports bitrate targeted by high quality. - MediaCodecInfo pickedEncoderInfo = filteredEncoderInfos.get(0); - int closestSupportedBitrate = - EncoderUtil.getSupportedBitrateRange(pickedEncoderInfo, mimeType).clamp(requestedBitrate); - VideoEncoderSettings.Builder supportedEncodingSettingBuilder = videoEncoderSettings.buildUpon(); Format.Builder encoderSupportedFormatBuilder = requestedFormat @@ -418,11 +448,23 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { .setSampleMimeType(mimeType) .setWidth(finalResolution.getWidth()) .setHeight(finalResolution.getHeight()); - - if (!videoEncoderSettings.enableHighQualityTargeting) { - supportedEncodingSettingBuilder.setBitrate(closestSupportedBitrate); - encoderSupportedFormatBuilder.setAverageBitrate(closestSupportedBitrate); + MediaCodecInfo pickedEncoderInfo = filteredEncoderInfos.get(0); + if (videoEncoderSettings.enableHighQualityTargeting) { + requestedBitrate = + new DeviceMappedEncoderBitrateProvider() + .getBitrate( + pickedEncoderInfo.getName(), + finalResolution.getWidth(), + finalResolution.getHeight(), + requestedFormat.frameRate); + // Resets the flag after getting a targeted bitrate, so that supportedEncodingSetting can have + // bitrate set. + supportedEncodingSettingBuilder.setEnableHighQualityTargeting(false); } + int closestSupportedBitrate = + EncoderUtil.getSupportedBitrateRange(pickedEncoderInfo, mimeType).clamp(requestedBitrate); + supportedEncodingSettingBuilder.setBitrate(closestSupportedBitrate); + encoderSupportedFormatBuilder.setAverageBitrate(closestSupportedBitrate); if (videoEncoderSettings.profile == VideoEncoderSettings.NO_VALUE || videoEncoderSettings.level == VideoEncoderSettings.NO_VALUE diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java index c630a76a6a..a7df903799 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java @@ -131,6 +131,96 @@ public class DefaultEncoderFactoryTest { assertThat(actualVideoFormat.height).isEqualTo(1080); } + @Test + public void + createForVideoEncoding_setFormatAverageBitrateUnsetVideoEncoderSettings_configuresEncoderUsingFormatAverageBitrate() + throws Exception { + Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); + requestedVideoFormat = requestedVideoFormat.buildUpon().setAverageBitrate(5_000_000).build(); + + Format actualVideoFormat = + new DefaultEncoderFactory.Builder(context) + .setRequestedVideoEncoderSettings(VideoEncoderSettings.DEFAULT) + .build() + .createForVideoEncoding( + requestedVideoFormat, + /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .getConfigurationFormat(); + + assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); + assertThat(actualVideoFormat.width).isEqualTo(1920); + assertThat(actualVideoFormat.height).isEqualTo(1080); + assertThat(actualVideoFormat.averageBitrate).isEqualTo(5_000_000); + } + + @Test + public void + createForVideoEncoding_unsetFormatAverageBitrateAndUnsetVideoEncoderSettingsBitrate_configuresEncoderUsingDefaultBitrateMapping() + throws Exception { + Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); + Format actualVideoFormat = + new DefaultEncoderFactory.Builder(context) + .build() + .createForVideoEncoding( + requestedVideoFormat, + /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .getConfigurationFormat(); + + assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); + assertThat(actualVideoFormat.width).isEqualTo(1920); + assertThat(actualVideoFormat.height).isEqualTo(1080); + // The default behavior is to use DefaultEncoderFactory#getSuggestedBitrate. + // 1920 * 1080 * 30 * 0.07 * 2. + assertThat(actualVideoFormat.averageBitrate).isEqualTo(8_709_120); + } + + @Test + public void + createForVideoEncoding_setFormatAverageBitrateAndSetVideoEncoderSettingHighQualityTargeting_configuresEncoderUsingHighQualityTargeting() + throws Exception { + Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); + requestedVideoFormat = requestedVideoFormat.buildUpon().setAverageBitrate(5_000_000).build(); + Format actualVideoFormat = + new DefaultEncoderFactory.Builder(context) + .setRequestedVideoEncoderSettings( + new VideoEncoderSettings.Builder().setEnableHighQualityTargeting(true).build()) + .build() + .createForVideoEncoding( + requestedVideoFormat, + /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .getConfigurationFormat(); + + assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); + assertThat(actualVideoFormat.width).isEqualTo(1920); + assertThat(actualVideoFormat.height).isEqualTo(1080); + // DeviceMappedEncoderBitrateProvider will produce 1920 * 1080 * 30 * 1.4, but the value is + // clampped down to the encoder's maximum, 25_000_000. + assertThat(actualVideoFormat.averageBitrate).isEqualTo(25_000_000); + } + + @Test + public void + createForVideoEncoding_setFormatAverageBitrateAndVideoEncoderSettingsBitrate_configuresEncoderUsingVideoEncoderSettingsBitrate() + throws Exception { + Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); + requestedVideoFormat = requestedVideoFormat.buildUpon().setAverageBitrate(5_000_000).build(); + + Format actualVideoFormat = + new DefaultEncoderFactory.Builder(context) + .setRequestedVideoEncoderSettings( + new VideoEncoderSettings.Builder().setBitrate(10_000_000).build()) + .build() + .createForVideoEncoding( + requestedVideoFormat, + /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .getConfigurationFormat(); + + assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); + assertThat(actualVideoFormat.width).isEqualTo(1920); + assertThat(actualVideoFormat.height).isEqualTo(1080); + assertThat(actualVideoFormat.averageBitrate).isEqualTo(10_000_000); + } + @Config(sdk = 29) @Test public void From 04f031d16805a6d6786d135f77d0f6e79c77c8f7 Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 29 Nov 2022 10:59:22 +0000 Subject: [PATCH 016/183] Bump cast sdk version and remove workaround for live duration The fix for b/171657375 (internal) has been shipped with 21.1.0 already (see https://developers.google.com/cast/docs/release-notes#august-8,-2022). PiperOrigin-RevId: 491583727 --- extensions/cast/build.gradle | 2 +- .../com/google/android/exoplayer2/ext/cast/CastUtils.java | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/extensions/cast/build.gradle b/extensions/cast/build.gradle index ba333edbe2..a7489a9eeb 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:21.0.1' + api 'com.google.android.gms:play-services-cast-framework:21.2.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/CastUtils.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastUtils.java index 5b96bc5846..af6cd8b21c 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 @@ -26,10 +26,6 @@ import com.google.android.gms.cast.MediaTrack; /** Utility methods for Cast integration. */ /* package */ final class CastUtils { - /** The duration returned by {@link MediaInfo#getStreamDuration()} for live streams. */ - // TODO: Remove once [Internal ref: b/171657375] is fixed. - private static final long LIVE_STREAM_DURATION = -1000; - /** * Returns the duration in microseconds advertised by a media info, or {@link C#TIME_UNSET} if * unknown or not applicable. @@ -42,9 +38,7 @@ import com.google.android.gms.cast.MediaTrack; return C.TIME_UNSET; } long durationMs = mediaInfo.getStreamDuration(); - return durationMs != MediaInfo.UNKNOWN_DURATION && durationMs != LIVE_STREAM_DURATION - ? Util.msToUs(durationMs) - : C.TIME_UNSET; + return durationMs != MediaInfo.UNKNOWN_DURATION ? Util.msToUs(durationMs) : C.TIME_UNSET; } /** From 532e0ffdc3d4feaca219f92007ea99e250b0213d Mon Sep 17 00:00:00 2001 From: claincly Date: Tue, 29 Nov 2022 13:49:15 +0000 Subject: [PATCH 017/183] Move video encoding MIME type fallback to VTSP Main change: - Removed `Codec.EncoderFactory.createForVideoEncoding`'s argument of a list of allowed MIME types - Moved the check for whether a video MIME type is supported to VTSP PiperOrigin-RevId: 491611799 --- .../transformer/AndroidTestUtil.java | 5 +- .../TransformerAndroidTestRunner.java | 5 +- .../transformer/TransformerEndToEndTest.java | 3 +- .../android/exoplayer2/transformer/Codec.java | 21 +++-- .../transformer/DefaultEncoderFactory.java | 73 ++++------------ .../exoplayer2/transformer/EncoderUtil.java | 19 ++--- .../VideoTranscodingSamplePipeline.java | 84 +++++++++++++++---- .../DefaultEncoderFactoryTest.java | 75 ++++------------- .../transformer/EncoderUtilTest.java | 24 ++++++ .../transformer/VideoEncoderWrapperTest.java | 44 +++++++++- 10 files changed, 190 insertions(+), 163 deletions(-) diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java index 5a2af177d0..21d3a5473c 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java @@ -478,9 +478,8 @@ public final class AndroidTestUtil { } @Override - public Codec createForVideoEncoding(Format format, List allowedMimeTypes) - throws TransformationException { - return encoderFactory.createForVideoEncoding(format, allowedMimeTypes); + public Codec createForVideoEncoding(Format format) throws TransformationException { + return encoderFactory.createForVideoEncoding(format); } @Override diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java index ad994fa30c..f6edebc7eb 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java @@ -454,9 +454,8 @@ public class TransformerAndroidTestRunner { } @Override - public Codec createForVideoEncoding(Format format, List allowedMimeTypes) - throws TransformationException { - Codec videoEncoder = encoderFactory.createForVideoEncoding(format, allowedMimeTypes); + public Codec createForVideoEncoding(Format format) throws TransformationException { + Codec videoEncoder = encoderFactory.createForVideoEncoding(format); videoEncoderName = videoEncoder.getName(); return videoEncoder; } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index 25eb95e7dd..55ce1bfb30 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -146,8 +146,7 @@ public class TransformerEndToEndTest { } @Override - public Codec createForVideoEncoding(Format format, List allowedMimeTypes) - throws TransformationException { + public Codec createForVideoEncoding(Format format) throws TransformationException { throw TransformationException.createForCodec( new IllegalArgumentException(), /* isVideo= */ true, diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java index cac8f56ef1..9b5d209283 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java @@ -87,23 +87,22 @@ public interface Codec { /** * Returns a {@link Codec} for video encoding. * - *

This method must validate that the {@link Codec} is configured to produce one of the - * {@code allowedMimeTypes}. The {@linkplain Format#sampleMimeType sample MIME type} given in - * {@code format} is not necessarily allowed. + *

The caller should ensure the {@linkplain Format#sampleMimeType MIME type} is supported on + * the device before calling this method. If encoding to HDR, the caller should also ensure the + * {@linkplain Format#colorInfo color characteristics} are supported. * * @param format The {@link Format} (of the output data) used to determine the underlying * encoder and its configuration values. {@link Format#sampleMimeType}, {@link Format#width} * and {@link Format#height} are set to those of the desired output video format. {@link - * Format#rotationDegrees} is 0 and {@link Format#width} {@code >=} {@link Format#height}, - * therefore the video is always in landscape orientation. {@link Format#frameRate} is set - * to the output video's frame rate, if available. - * @param allowedMimeTypes The non-empty list of allowed output sample {@linkplain MimeTypes - * MIME types}. - * @return A {@link Codec} for video encoding. + * Format#frameRate} is set to the requested output frame rate, if available. {@link + * Format#colorInfo} is set to the requested output color characteristics, if available. + * {@link Format#rotationDegrees} is 0 and {@link Format#width} {@code >=} {@link + * Format#height}, therefore the video is always in landscape orientation. + * @return A {@link Codec} for encoding video to the requested {@linkplain Format#sampleMimeType + * MIME type}. * @throws TransformationException If no suitable {@link Codec} can be created. */ - Codec createForVideoEncoding(Format format, List allowedMimeTypes) - throws TransformationException; + Codec createForVideoEncoding(Format format) throws TransformationException; /** Returns whether the audio needs to be encoded because of encoder specific configuration. */ default boolean audioNeedsEncoding() { diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java index 24480ebe13..4dbcb397f5 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.transformer; +import static com.google.android.exoplayer2.transformer.TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED; 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.Assertions.checkState; @@ -211,21 +212,9 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { * VideoEncoderSettings#bitrate} set to request for a specific encoding bitrate. Bitrate settings * in {@link Format} are ignored when {@link VideoEncoderSettings#bitrate} or {@link * VideoEncoderSettings#enableHighQualityTargeting} is set. - * - * @param format The {@link Format} (of the output data) used to determine the underlying encoder - * and its configuration values. {@link Format#sampleMimeType}, {@link Format#width} and - * {@link Format#height} are set to those of the desired output video format. {@link - * Format#rotationDegrees} is 0 and {@link Format#width} {@code >=} {@link Format#height}, - * therefore the video is always in landscape orientation. {@link Format#frameRate} is set to - * the output video's frame rate, if available. - * @param allowedMimeTypes The non-empty list of allowed output sample {@linkplain MimeTypes MIME - * types}. - * @return A {@link DefaultCodec} for video encoding. - * @throws TransformationException If no suitable {@link DefaultCodec} can be created. */ @Override - public Codec createForVideoEncoding(Format format, List allowedMimeTypes) - throws TransformationException { + public DefaultCodec createForVideoEncoding(Format format) throws TransformationException { if (format.frameRate == Format.NO_VALUE) { format = format.buildUpon().setFrameRate(DEFAULT_FRAME_RATE).build(); } @@ -236,17 +225,12 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { checkArgument(format.height <= format.width); checkArgument(format.rotationDegrees == 0); checkNotNull(format.sampleMimeType); - checkArgument(!allowedMimeTypes.isEmpty()); checkStateNotNull(videoEncoderSelector); @Nullable VideoEncoderQueryResult encoderAndClosestFormatSupport = findEncoderWithClosestSupportedFormat( - format, - requestedVideoEncoderSettings, - videoEncoderSelector, - allowedMimeTypes, - enableFallback); + format, requestedVideoEncoderSettings, videoEncoderSelector, enableFallback); if (encoderAndClosestFormatSupport == null) { throw createTransformationException(format); @@ -310,13 +294,14 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { MediaFormatUtil.maybeSetColorInfo(mediaFormat, encoderSupportedFormat.colorInfo); if (Util.SDK_INT >= 31 && ColorInfo.isTransferHdr(format.colorInfo)) { + // TODO(b/260389841): Validate the picked encoder supports HDR editing. if (EncoderUtil.getSupportedColorFormats(encoderInfo, mimeType) .contains(MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010)) { mediaFormat.setInteger( MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010); } else { - throw createTransformationException(format); + throw createTransformationException(format, ERROR_CODE_HDR_ENCODING_UNSUPPORTED); } } else { mediaFormat.setInteger( @@ -380,15 +365,8 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { Format requestedFormat, VideoEncoderSettings videoEncoderSettings, EncoderSelector encoderSelector, - List allowedMimeTypes, boolean enableFallback) { - String requestedMimeType = requestedFormat.sampleMimeType; - @Nullable - String mimeType = findFallbackMimeType(encoderSelector, requestedMimeType, allowedMimeTypes); - if (mimeType == null || (!enableFallback && !requestedMimeType.equals(mimeType))) { - return null; - } - + String mimeType = checkNotNull(requestedFormat.sampleMimeType); ImmutableList filteredEncoderInfos = encoderSelector.selectEncoderInfos(mimeType); if (filteredEncoderInfos.isEmpty()) { @@ -678,36 +656,6 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { return ImmutableList.copyOf(filteredEncoders); } - /** - * Finds a {@linkplain MimeTypes MIME type} that is supported by the encoder and in the {@code - * allowedMimeTypes}. - */ - @Nullable - private static String findFallbackMimeType( - EncoderSelector encoderSelector, String requestedMimeType, List allowedMimeTypes) { - if (mimeTypeIsSupported(encoderSelector, requestedMimeType, allowedMimeTypes)) { - return requestedMimeType; - } else if (mimeTypeIsSupported(encoderSelector, MimeTypes.VIDEO_H265, allowedMimeTypes)) { - return MimeTypes.VIDEO_H265; - } else if (mimeTypeIsSupported(encoderSelector, MimeTypes.VIDEO_H264, allowedMimeTypes)) { - return MimeTypes.VIDEO_H264; - } else { - for (int i = 0; i < allowedMimeTypes.size(); i++) { - String allowedMimeType = allowedMimeTypes.get(i); - if (mimeTypeIsSupported(encoderSelector, allowedMimeType, allowedMimeTypes)) { - return allowedMimeType; - } - } - } - return null; - } - - private static boolean mimeTypeIsSupported( - EncoderSelector encoderSelector, String mimeType, List allowedMimeTypes) { - return !encoderSelector.selectEncoderInfos(mimeType).isEmpty() - && allowedMimeTypes.contains(mimeType); - } - /** * Computes the video bit rate using the Kush Gauge. * @@ -730,12 +678,19 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { @RequiresNonNull("#1.sampleMimeType") private static TransformationException createTransformationException(Format format) { + return createTransformationException( + format, TransformationException.ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED); + } + + @RequiresNonNull("#1.sampleMimeType") + private static TransformationException createTransformationException( + Format format, @TransformationException.ErrorCode int errorCode) { return TransformationException.createForCodec( new IllegalArgumentException("The requested encoding format is not supported."), MimeTypes.isVideo(format.sampleMimeType), /* isDecoder= */ false, format, /* mediaCodecName= */ null, - TransformationException.ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED); + errorCode); } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java index b86c808840..dc1126b7ec 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java @@ -69,8 +69,8 @@ public final class EncoderUtil { } /** - * Returns the names of encoders that support HDR editing for the given format, or an empty list - * if the format is unknown or not supported for HDR encoding. + * Returns the names of encoders that support HDR editing for the given {@code mimeType} and + * {@code ColorInfo}, or an empty list if the format is unknown or not supported for HDR encoding. */ public static ImmutableList getSupportedEncoderNamesForHdrEditing( String mimeType, @Nullable ColorInfo colorInfo) { @@ -78,13 +78,12 @@ public final class EncoderUtil { return ImmutableList.of(); } - @ColorTransfer int colorTransfer = colorInfo.colorTransfer; - ImmutableList profiles = getCodecProfilesForHdrFormat(mimeType, colorTransfer); - ImmutableList.Builder resultBuilder = ImmutableList.builder(); - ImmutableList mediaCodecInfos = - EncoderSelector.DEFAULT.selectEncoderInfos(mimeType); - for (int i = 0; i < mediaCodecInfos.size(); i++) { - MediaCodecInfo mediaCodecInfo = mediaCodecInfos.get(i); + ImmutableList encoders = getSupportedEncoders(mimeType); + ImmutableList allowedColorProfiles = + getCodecProfilesForHdrFormat(mimeType, colorInfo.colorTransfer); + ImmutableList.Builder resultBuilder = new ImmutableList.Builder<>(); + for (int i = 0; i < encoders.size(); i++) { + MediaCodecInfo mediaCodecInfo = encoders.get(i); if (mediaCodecInfo.isAlias() || !isFeatureSupported( mediaCodecInfo, mimeType, MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing)) { @@ -92,7 +91,7 @@ public final class EncoderUtil { } for (MediaCodecInfo.CodecProfileLevel codecProfileLevel : mediaCodecInfo.getCapabilitiesForType(mimeType).profileLevels) { - if (profiles.contains(codecProfileLevel.profile)) { + if (allowedColorProfiles.contains(codecProfileLevel.profile)) { resultBuilder.add(mediaCodecInfo.getName()); } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java index 7178c28377..9dfd6f0589 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer2.transformer; 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.SDK_INT; import android.content.Context; @@ -36,6 +37,7 @@ import com.google.android.exoplayer2.util.FrameInfo; import com.google.android.exoplayer2.util.FrameProcessingException; import com.google.android.exoplayer2.util.FrameProcessor; import com.google.android.exoplayer2.util.Log; +import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.SurfaceInfo; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.ColorInfo; @@ -369,7 +371,7 @@ import org.checkerframework.dataflow.qual.Pure; private final Codec.EncoderFactory encoderFactory; private final Format inputFormat; - private final List allowedOutputMimeTypes; + private final List muxerSupportedMimeTypes; private final TransformationRequest transformationRequest; private final FallbackListener fallbackListener; private final String requestedOutputMimeType; @@ -384,12 +386,12 @@ import org.checkerframework.dataflow.qual.Pure; public EncoderWrapper( Codec.EncoderFactory encoderFactory, Format inputFormat, - List allowedOutputMimeTypes, + List muxerSupportedMimeTypes, TransformationRequest transformationRequest, FallbackListener fallbackListener) { this.encoderFactory = encoderFactory; this.inputFormat = inputFormat; - this.allowedOutputMimeTypes = allowedOutputMimeTypes; + this.muxerSupportedMimeTypes = muxerSupportedMimeTypes; this.transformationRequest = transformationRequest; this.fallbackListener = fallbackListener; @@ -454,20 +456,31 @@ import org.checkerframework.dataflow.qual.Pure; .setColorInfo(getSupportedInputColor()) .build(); + @Nullable + String supportedMimeType = + selectEncoderAndMuxerSupportedMimeType( + requestedOutputMimeType, muxerSupportedMimeTypes, requestedEncoderFormat.colorInfo); + if (supportedMimeType == null) { + throw TransformationException.createForCodec( + new IllegalArgumentException("No MIME type is supported by both encoder and muxer."), + /* isVideo= */ true, + /* isDecoder= */ false, + requestedEncoderFormat, + /* mediaCodecName= */ null, + TransformationException.ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED); + } + encoder = - encoderFactory.createForVideoEncoding(requestedEncoderFormat, allowedOutputMimeTypes); + encoderFactory.createForVideoEncoding( + requestedEncoderFormat.buildUpon().setSampleMimeType(supportedMimeType).build()); Format encoderSupportedFormat = encoder.getConfigurationFormat(); - if (ColorInfo.isTransferHdr(requestedEncoderFormat.colorInfo)) { - if (!requestedOutputMimeType.equals(encoderSupportedFormat.sampleMimeType)) { - throw createEncodingException( - new IllegalStateException("MIME type fallback unsupported with HDR editing"), - encoderSupportedFormat); - } else if (!supportedEncoderNamesForHdrEditing.contains(encoder.getName())) { - throw createEncodingException( - new IllegalStateException("Selected encoder doesn't support HDR editing"), - encoderSupportedFormat); - } + checkState(supportedMimeType.equals(encoderSupportedFormat.sampleMimeType)); + if (ColorInfo.isTransferHdr(requestedEncoderFormat.colorInfo) + && !supportedEncoderNamesForHdrEditing.contains(encoder.getName())) { + throw createEncodingException( + new IllegalStateException("Selected encoder doesn't support HDR editing"), + encoderSupportedFormat); } boolean isInputToneMapped = ColorInfo.isTransferHdr(inputFormat.colorInfo) @@ -553,5 +566,48 @@ import org.checkerframework.dataflow.qual.Pure; checkNotNull(encoder).getName(), TransformationException.ERROR_CODE_ENCODING_FAILED); } + + /** + * Finds a {@linkplain MimeTypes MIME type} that is supported by both the encoder and the muxer. + * + * @param requestedMimeType The requested {@linkplain MimeTypes MIME type}. + * @param muxerSupportedMimeTypes The list of sample {@linkplain MimeTypes MIME types} that the + * muxer supports. + * @param colorInfo The requested encoding {@link ColorInfo}, if available. + * @return A {@linkplain MimeTypes MIME type} that is supported by an encoder and the muxer, or + * {@code null} if no such {@linkplain MimeTypes MIME type} exists. + */ + @Nullable + private static String selectEncoderAndMuxerSupportedMimeType( + String requestedMimeType, + List muxerSupportedMimeTypes, + @Nullable ColorInfo colorInfo) { + ImmutableList mimeTypesToCheck = + new ImmutableList.Builder() + .add(requestedMimeType) + .add(MimeTypes.VIDEO_H265) + .add(MimeTypes.VIDEO_H264) + .addAll(muxerSupportedMimeTypes) + .build(); + + for (int i = 0; i < mimeTypesToCheck.size(); i++) { + String mimeType = mimeTypesToCheck.get(i); + if (mimeTypeAndColorAreSupported(mimeType, muxerSupportedMimeTypes, colorInfo)) { + return mimeType; + } + } + return null; + } + + private static boolean mimeTypeAndColorAreSupported( + String mimeType, List muxerSupportedMimeTypes, @Nullable ColorInfo colorInfo) { + if (!muxerSupportedMimeTypes.contains(mimeType)) { + return false; + } + if (ColorInfo.isTransferHdr(colorInfo)) { + return !EncoderUtil.getSupportedEncoderNamesForHdrEditing(mimeType, colorInfo).isEmpty(); + } + return !EncoderUtil.getSupportedEncoders(mimeType).isEmpty(); + } } } diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java index a7df903799..d280d94544 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer2.transformer; import static androidx.test.core.app.ApplicationProvider.getApplicationContext; +import static com.google.android.exoplayer2.transformer.TransformationException.ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; @@ -84,9 +85,7 @@ public class DefaultEncoderFactoryTest { Format actualVideoFormat = new DefaultEncoderFactory.Builder(context) .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .createForVideoEncoding(requestedVideoFormat) .getConfigurationFormat(); assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); @@ -97,22 +96,15 @@ public class DefaultEncoderFactoryTest { } @Test - public void createForVideoEncoding_withFallbackOnAndUnsupportedMimeType_configuresEncoder() - throws Exception { + public void createForVideoEncoding_withFallbackOnAndUnsupportedMimeType_throws() { Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H265, 1920, 1080, 30); - Format actualVideoFormat = - new DefaultEncoderFactory.Builder(context) - .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) - .getConfigurationFormat(); + DefaultEncoderFactory encoderFactory = new DefaultEncoderFactory.Builder(context).build(); - assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); - assertThat(actualVideoFormat.width).isEqualTo(1920); - assertThat(actualVideoFormat.height).isEqualTo(1080); - // 1920 * 1080 * 30 * 0.07 * 2. - assertThat(actualVideoFormat.averageBitrate).isEqualTo(8_709_120); + TransformationException transformationException = + assertThrows( + TransformationException.class, + () -> encoderFactory.createForVideoEncoding(requestedVideoFormat)); + assertThat(transformationException.errorCode).isEqualTo(ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED); } @Test @@ -122,9 +114,7 @@ public class DefaultEncoderFactoryTest { Format actualVideoFormat = new DefaultEncoderFactory.Builder(context) .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .createForVideoEncoding(requestedVideoFormat) .getConfigurationFormat(); assertThat(actualVideoFormat.width).isEqualTo(1920); @@ -142,9 +132,7 @@ public class DefaultEncoderFactoryTest { new DefaultEncoderFactory.Builder(context) .setRequestedVideoEncoderSettings(VideoEncoderSettings.DEFAULT) .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .createForVideoEncoding(requestedVideoFormat) .getConfigurationFormat(); assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); @@ -161,9 +149,7 @@ public class DefaultEncoderFactoryTest { Format actualVideoFormat = new DefaultEncoderFactory.Builder(context) .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .createForVideoEncoding(requestedVideoFormat) .getConfigurationFormat(); assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); @@ -185,9 +171,7 @@ public class DefaultEncoderFactoryTest { .setRequestedVideoEncoderSettings( new VideoEncoderSettings.Builder().setEnableHighQualityTargeting(true).build()) .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .createForVideoEncoding(requestedVideoFormat) .getConfigurationFormat(); assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); @@ -210,9 +194,7 @@ public class DefaultEncoderFactoryTest { .setRequestedVideoEncoderSettings( new VideoEncoderSettings.Builder().setBitrate(10_000_000).build()) .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .createForVideoEncoding(requestedVideoFormat) .getConfigurationFormat(); assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); @@ -230,9 +212,7 @@ public class DefaultEncoderFactoryTest { Codec videoEncoder = new DefaultEncoderFactory.Builder(context) .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)); + .createForVideoEncoding(requestedVideoFormat); assertThat(videoEncoder).isInstanceOf(DefaultCodec.class); MediaFormat configurationMediaFormat = @@ -244,25 +224,6 @@ public class DefaultEncoderFactoryTest { .isEqualTo(Integer.MAX_VALUE); } - @Test - public void createForVideoEncoding_withNoSupportedEncoder_throws() { - Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); - - TransformationException exception = - assertThrows( - TransformationException.class, - () -> - new DefaultEncoderFactory.Builder(context) - .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H265))); - - assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); - assertThat(exception.errorCode) - .isEqualTo(TransformationException.ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED); - } - @Test public void createForVideoEncoding_withNoAvailableEncoderFromEncoderSelector_throws() { Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); @@ -270,11 +231,9 @@ public class DefaultEncoderFactoryTest { TransformationException.class, () -> new DefaultEncoderFactory.Builder(context) - .setVideoEncoderSelector(mimeType -> ImmutableList.of()) + .setVideoEncoderSelector((mimeType) -> ImmutableList.of()) .build() - .createForVideoEncoding( - requestedVideoFormat, - /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264))); + .createForVideoEncoding(requestedVideoFormat)); } private static Format createVideoFormat(String mimeType, int width, int height, int frameRate) { diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/EncoderUtilTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/EncoderUtilTest.java index 022e4cbefc..56eb3e8ef1 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/EncoderUtilTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/EncoderUtilTest.java @@ -23,11 +23,14 @@ import android.media.MediaFormat; import android.util.Size; import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.MimeTypes; +import com.google.android.exoplayer2.video.ColorInfo; import com.google.common.collect.ImmutableList; 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.ShadowMediaCodecList; @@ -116,4 +119,25 @@ public class EncoderUtilTest { assertThat(closestSupportedResolution.getWidth()).isEqualTo(1920); assertThat(closestSupportedResolution.getHeight()).isEqualTo(1080); } + + /** + * @see EncoderUtil#getSupportedEncoderNamesForHdrEditing(String, ColorInfo) + */ + @Config(sdk = {30, 31}) + @Test + public void getSupportedEncoderNamesForHdrEditing_returnsEmptyList() { + // This test is run on 30 and 31 because the tested logic differentiate at API31. + // getSupportedEncoderNamesForHdrEditing returns an empty list for API < 31. It returns an empty + // list for API >= 31 as well, because currently it is not possible to make ShadowMediaCodec + // support HDR. + assertThat( + EncoderUtil.getSupportedEncoderNamesForHdrEditing( + MIME_TYPE, + new ColorInfo( + C.COLOR_SPACE_BT2020, + C.COLOR_RANGE_FULL, + C.COLOR_TRANSFER_HLG, + /* hdrStaticInfo= */ null))) + .isEmpty(); + } } diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java index fe17980468..9fc8a231ff 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java @@ -19,6 +19,8 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.media.MediaCodecInfo; +import android.media.MediaFormat; import android.net.Uri; import android.os.Looper; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -34,6 +36,8 @@ import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.shadows.MediaCodecInfoBuilder; +import org.robolectric.shadows.ShadowMediaCodecList; /** Unit tests for {@link VideoTranscodingSamplePipeline.EncoderWrapper}. */ @RunWith(AndroidJUnit4.class) @@ -49,14 +53,15 @@ public final class VideoEncoderWrapperTest { private final VideoTranscodingSamplePipeline.EncoderWrapper encoderWrapper = new VideoTranscodingSamplePipeline.EncoderWrapper( fakeEncoderFactory, - /* inputFormat= */ new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_H265).build(), - /* allowedOutputMimeTypes= */ ImmutableList.of(), + /* inputFormat= */ new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_H264).build(), + /* muxerSupportedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264), emptyTransformationRequest, fallbackListener); @Before public void registerTrack() { fallbackListener.registerTrack(); + createShadowH264Encoder(); } @Test @@ -111,6 +116,39 @@ public final class VideoEncoderWrapperTest { assertThat(surfaceInfo.height).isEqualTo(fallbackHeight); } + private static void createShadowH264Encoder() { + MediaFormat avcFormat = new MediaFormat(); + avcFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC); + MediaCodecInfo.CodecProfileLevel profileLevel = new MediaCodecInfo.CodecProfileLevel(); + profileLevel.profile = MediaCodecInfo.CodecProfileLevel.AVCProfileHigh; + // Using Level4 gives us 8192 16x16 blocks. If using width 1920 uses 120 blocks, 8192 / 120 = 68 + // blocks will be left for encoding height 1088. + profileLevel.level = MediaCodecInfo.CodecProfileLevel.AVCLevel4; + + createShadowVideoEncoder(avcFormat, profileLevel, "test.transformer.avc.encoder"); + } + + private static void createShadowVideoEncoder( + MediaFormat supportedFormat, + MediaCodecInfo.CodecProfileLevel supportedProfileLevel, + String name) { + // ShadowMediaCodecList is static. The added encoders will be visible for every test. + ShadowMediaCodecList.addCodec( + MediaCodecInfoBuilder.newBuilder() + .setName(name) + .setIsEncoder(true) + .setCapabilities( + MediaCodecInfoBuilder.CodecCapabilitiesBuilder.newBuilder() + .setMediaFormat(supportedFormat) + .setIsEncoder(true) + .setColorFormats( + new int[] {MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible}) + .setProfileLevels( + new MediaCodecInfo.CodecProfileLevel[] {supportedProfileLevel}) + .build()) + .build()); + } + private static class FakeVideoEncoderFactory implements Codec.EncoderFactory { private int fallbackWidth; @@ -132,7 +170,7 @@ public final class VideoEncoderWrapperTest { } @Override - public Codec createForVideoEncoding(Format format, List allowedMimeTypes) { + public Codec createForVideoEncoding(Format format) { Codec mockEncoder = mock(Codec.class); if (fallbackWidth != C.LENGTH_UNSET) { format = format.buildUpon().setWidth(fallbackWidth).build(); From 4cf877b81428021c4eb2dfa1a743178f280aceb5 Mon Sep 17 00:00:00 2001 From: tonihei Date: Tue, 29 Nov 2022 14:01:35 +0000 Subject: [PATCH 018/183] Add configuration to support OPUS offload To support OPUS offload, we need to provide a few configuration values that are currently not set due to the lack of devices supporting OPUS offload. PiperOrigin-RevId: 491613716 --- .../java/com/google/android/exoplayer2/C.java | 9 +- .../android/exoplayer2/util/MimeTypes.java | 2 + .../exoplayer2/audio/DefaultAudioSink.java | 2 + .../DefaultAudioTrackBufferSizeProvider.java | 2 + .../android/exoplayer2/audio/OpusUtil.java | 59 ++ .../exoplayer2/extractor/ogg/OpusReader.java | 38 +- .../exoplayer2/audio/OpusUtilTest.java | 575 +++++++++++++++++- 7 files changed, 646 insertions(+), 41 deletions(-) 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 d6d074c736..ce6d067805 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 @@ -194,7 +194,7 @@ public final class C { * #ENCODING_PCM_16BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_24BIT}, {@link #ENCODING_PCM_32BIT}, * {@link #ENCODING_PCM_FLOAT}, {@link #ENCODING_MP3}, {@link #ENCODING_AC3}, {@link * #ENCODING_E_AC3}, {@link #ENCODING_E_AC3_JOC}, {@link #ENCODING_AC4}, {@link #ENCODING_DTS}, - * {@link #ENCODING_DTS_HD} or {@link #ENCODING_DOLBY_TRUEHD}. + * {@link #ENCODING_DTS_HD}, {@link #ENCODING_DOLBY_TRUEHD} or {@link #ENCODING_OPUS}. */ @Documented @Retention(RetentionPolicy.SOURCE) @@ -221,7 +221,8 @@ public final class C { ENCODING_AC4, ENCODING_DTS, ENCODING_DTS_HD, - ENCODING_DOLBY_TRUEHD + ENCODING_DOLBY_TRUEHD, + ENCODING_OPUS, }) public @interface Encoding {} @@ -321,6 +322,10 @@ public final class C { * @see AudioFormat#ENCODING_DOLBY_TRUEHD */ public static final int ENCODING_DOLBY_TRUEHD = AudioFormat.ENCODING_DOLBY_TRUEHD; + /** + * @see AudioFormat#ENCODING_OPUS + */ + public static final int ENCODING_OPUS = AudioFormat.ENCODING_OPUS; /** Represents the behavior affecting whether spatialization will be used. */ @Documented 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 479b213395..fa3530c316 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 @@ -567,6 +567,8 @@ public final class MimeTypes { return C.ENCODING_DTS_HD; case MimeTypes.AUDIO_TRUEHD: return C.ENCODING_DOLBY_TRUEHD; + case MimeTypes.AUDIO_OPUS: + return C.ENCODING_OPUS; default: return C.ENCODING_INVALID; } 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 3e7222ebb1..678863e2c9 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 @@ -1666,6 +1666,8 @@ public final class DefaultAudioSink implements AudioSink { ? 0 : (Ac3Util.parseTrueHdSyncframeAudioSampleCount(buffer, syncframeOffset) * Ac3Util.TRUEHD_RECHUNK_SAMPLE_COUNT); + case C.ENCODING_OPUS: + return OpusUtil.parsePacketAudioSampleCount(buffer); case C.ENCODING_PCM_16BIT: case C.ENCODING_PCM_16BIT_BIG_ENDIAN: case C.ENCODING_PCM_24BIT: diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProvider.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProvider.java index 59faf13f87..c9cc38fd53 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProvider.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProvider.java @@ -248,6 +248,8 @@ public class DefaultAudioTrackBufferSizeProvider return DtsUtil.DTS_HD_MAX_RATE_BYTES_PER_SECOND; case C.ENCODING_DOLBY_TRUEHD: return Ac3Util.TRUEHD_MAX_RATE_BYTES_PER_SECOND; + case C.ENCODING_OPUS: + return OpusUtil.MAX_BYTES_PER_SECOND; case C.ENCODING_PCM_16BIT: case C.ENCODING_PCM_16BIT_BIG_ENDIAN: case C.ENCODING_PCM_24BIT: diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/audio/OpusUtil.java b/library/extractor/src/main/java/com/google/android/exoplayer2/audio/OpusUtil.java index 70b1e96a8c..5a9031991a 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/audio/OpusUtil.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/audio/OpusUtil.java @@ -27,6 +27,9 @@ public class OpusUtil { /** Opus streams are always 48000 Hz. */ public static final int SAMPLE_RATE = 48_000; + /** Maximum achievable Opus bitrate. */ + public static final int MAX_BYTES_PER_SECOND = 510 * 1000 / 8; // See RFC 6716. Section 2.1.1 + private static final int DEFAULT_SEEK_PRE_ROLL_SAMPLES = 3840; private static final int FULL_CODEC_INITIALIZATION_DATA_BUFFER_COUNT = 3; @@ -61,6 +64,62 @@ public class OpusUtil { return initializationData; } + /** + * Returns the number of audio samples in the given audio packet. + * + *

The buffer's position is not modified. + * + * @param buffer The audio packet. + * @return Returns the number of audio samples in the packet. + */ + public static int parsePacketAudioSampleCount(ByteBuffer buffer) { + long packetDurationUs = + getPacketDurationUs(buffer.get(0), buffer.limit() > 1 ? buffer.get(1) : 0); + return (int) (packetDurationUs * SAMPLE_RATE / C.MICROS_PER_SECOND); + } + + /** + * Returns the duration of the given audio packet. + * + * @param buffer The audio packet. + * @return Returns the duration of the given audio packet, in microseconds. + */ + public static long getPacketDurationUs(byte[] buffer) { + return getPacketDurationUs(buffer[0], buffer.length > 1 ? buffer[1] : 0); + } + + private static long getPacketDurationUs(byte packetByte0, byte packetByte1) { + // See RFC6716, Sections 3.1 and 3.2. + int toc = packetByte0 & 0xFF; + int frames; + switch (toc & 0x3) { + case 0: + frames = 1; + break; + case 1: + case 2: + frames = 2; + break; + default: + frames = packetByte1 & 0x3F; + break; + } + + int config = toc >> 3; + int length = config & 0x3; + int frameDurationUs; + if (config >= 16) { + frameDurationUs = 2500 << length; + } else if (config >= 12) { + frameDurationUs = 10000 << (length & 0x1); + } else if (length == 3) { + frameDurationUs = 60000; + } else { + frameDurationUs = 10000 << length; + } + return (long) frames * frameDurationUs; + } + private static int getPreSkipSamples(byte[] header) { return ((header[11] & 0xFF) << 8) | (header[10] & 0xFF); } 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 531774f93c..6e7051aa14 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 @@ -54,7 +54,7 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; @Override protected long preparePayload(ParsableByteArray packet) { - return convertTimeToGranule(getPacketDurationUs(packet.getData())); + return convertTimeToGranule(OpusUtil.getPacketDurationUs(packet.getData())); } @Override @@ -121,42 +121,6 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; } } - /** - * Returns the duration of the given audio packet. - * - * @param packet Contains audio data. - * @return Returns the duration of the given audio packet. - */ - private long getPacketDurationUs(byte[] packet) { - int toc = packet[0] & 0xFF; - int frames; - switch (toc & 0x3) { - case 0: - frames = 1; - break; - case 1: - case 2: - frames = 2; - break; - default: - frames = packet[1] & 0x3F; - break; - } - - int config = toc >> 3; - int length = config & 0x3; - if (config >= 16) { - length = 2500 << length; - } else if (config >= 12) { - length = 10000 << (length & 0x1); - } else if (length == 3) { - length = 60000; - } else { - length = 10000 << length; - } - return (long) frames * length; - } - /** * Returns true if the given {@link ParsableByteArray} starts with {@code expectedPrefix}. Does * not change the {@link ParsableByteArray#getPosition() position} of {@code packet}. diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/audio/OpusUtilTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/audio/OpusUtilTest.java index d3026359c2..f7eb4e7b18 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/audio/OpusUtilTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/audio/OpusUtilTest.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.audio; +import static com.google.android.exoplayer2.util.Util.getBytesFromHexString; import static com.google.common.truth.Truth.assertThat; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -41,8 +42,9 @@ public final class OpusUtilTest { buildNativeOrderByteArray(sampleCountToNanoseconds(DEFAULT_SEEK_PRE_ROLL_SAMPLES)); @Test - public void buildInitializationData() { + public void buildInitializationData_returnsExpectedHeaderWithPreSkipAndPreRoll() { List initializationData = OpusUtil.buildInitializationData(HEADER); + assertThat(initializationData).hasSize(3); assertThat(initializationData.get(0)).isEqualTo(HEADER); assertThat(initializationData.get(1)).isEqualTo(HEADER_PRE_SKIP_BYTES); @@ -50,11 +52,576 @@ public final class OpusUtilTest { } @Test - public void getChannelCount() { + public void getChannelCount_returnsChannelCount() { int channelCount = OpusUtil.getChannelCount(HEADER); + assertThat(channelCount).isEqualTo(2); } + @Test + public void getPacketDurationUs_code0_returnsExpectedDuration() { + long config0DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("04")); + long config1DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("0C")); + long config2DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("14")); + long config3DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("1C")); + long config4DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("24")); + long config5DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("2C")); + long config6DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("34")); + long config7DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("3C")); + long config8DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("44")); + long config9DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("4C")); + long config10DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("54")); + long config11DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("5C")); + long config12DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("64")); + long config13DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("6C")); + long config14DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("74")); + long config15DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("7C")); + long config16DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("84")); + long config17DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("8C")); + long config18DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("94")); + long config19DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("9C")); + long config20DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("A4")); + long config21DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("AC")); + long config22DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("B4")); + long config23DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("BC")); + long config24DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("C4")); + long config25DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("CC")); + long config26DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("D4")); + long config27DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("DC")); + long config28DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("E4")); + long config29DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("EC")); + long config30DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("F4")); + long config31DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("FC")); + + assertThat(config0DurationUs).isEqualTo(10_000); + assertThat(config1DurationUs).isEqualTo(20_000); + assertThat(config2DurationUs).isEqualTo(40_000); + assertThat(config3DurationUs).isEqualTo(60_000); + assertThat(config4DurationUs).isEqualTo(10_000); + assertThat(config5DurationUs).isEqualTo(20_000); + assertThat(config6DurationUs).isEqualTo(40_000); + assertThat(config7DurationUs).isEqualTo(60_000); + assertThat(config8DurationUs).isEqualTo(10_000); + assertThat(config9DurationUs).isEqualTo(20_000); + assertThat(config10DurationUs).isEqualTo(40_000); + assertThat(config11DurationUs).isEqualTo(60_000); + assertThat(config12DurationUs).isEqualTo(10_000); + assertThat(config13DurationUs).isEqualTo(20_000); + assertThat(config14DurationUs).isEqualTo(10_000); + assertThat(config15DurationUs).isEqualTo(20_000); + assertThat(config16DurationUs).isEqualTo(2_500); + assertThat(config17DurationUs).isEqualTo(5_000); + assertThat(config18DurationUs).isEqualTo(10_000); + assertThat(config19DurationUs).isEqualTo(20_000); + assertThat(config20DurationUs).isEqualTo(2_500); + assertThat(config21DurationUs).isEqualTo(5_000); + assertThat(config22DurationUs).isEqualTo(10_000); + assertThat(config23DurationUs).isEqualTo(20_000); + assertThat(config24DurationUs).isEqualTo(2_500); + assertThat(config25DurationUs).isEqualTo(5_000); + assertThat(config26DurationUs).isEqualTo(10_000); + assertThat(config27DurationUs).isEqualTo(20_000); + assertThat(config28DurationUs).isEqualTo(2_500); + assertThat(config29DurationUs).isEqualTo(5_000); + assertThat(config30DurationUs).isEqualTo(10_000); + assertThat(config31DurationUs).isEqualTo(20_000); + } + + @Test + public void getPacketDurationUs_code1_returnsExpectedDuration() { + long config0DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("05")); + long config1DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("0D")); + long config2DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("15")); + long config3DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("1D")); + long config4DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("25")); + long config5DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("2D")); + long config6DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("35")); + long config7DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("3D")); + long config8DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("45")); + long config9DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("4D")); + long config10DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("55")); + long config11DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("5D")); + long config12DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("65")); + long config13DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("6D")); + long config14DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("75")); + long config15DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("7D")); + long config16DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("85")); + long config17DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("8D")); + long config18DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("95")); + long config19DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("9D")); + long config20DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("A5")); + long config21DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("AD")); + long config22DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("B5")); + long config23DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("BD")); + long config24DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("C5")); + long config25DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("CD")); + long config26DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("D5")); + long config27DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("DD")); + long config28DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("E5")); + long config29DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("ED")); + long config30DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("F5")); + long config31DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("FD")); + + assertThat(config0DurationUs).isEqualTo(20_000); + assertThat(config1DurationUs).isEqualTo(40_000); + assertThat(config2DurationUs).isEqualTo(80_000); + assertThat(config3DurationUs).isEqualTo(120_000); + assertThat(config4DurationUs).isEqualTo(20_000); + assertThat(config5DurationUs).isEqualTo(40_000); + assertThat(config6DurationUs).isEqualTo(80_000); + assertThat(config7DurationUs).isEqualTo(120_000); + assertThat(config8DurationUs).isEqualTo(20_000); + assertThat(config9DurationUs).isEqualTo(40_000); + assertThat(config10DurationUs).isEqualTo(80_000); + assertThat(config11DurationUs).isEqualTo(120_000); + assertThat(config12DurationUs).isEqualTo(20_000); + assertThat(config13DurationUs).isEqualTo(40_000); + assertThat(config14DurationUs).isEqualTo(20_000); + assertThat(config15DurationUs).isEqualTo(40_000); + assertThat(config16DurationUs).isEqualTo(5_000); + assertThat(config17DurationUs).isEqualTo(10_000); + assertThat(config18DurationUs).isEqualTo(20_000); + assertThat(config19DurationUs).isEqualTo(40_000); + assertThat(config20DurationUs).isEqualTo(5_000); + assertThat(config21DurationUs).isEqualTo(10_000); + assertThat(config22DurationUs).isEqualTo(20_000); + assertThat(config23DurationUs).isEqualTo(40_000); + assertThat(config24DurationUs).isEqualTo(5_000); + assertThat(config25DurationUs).isEqualTo(10_000); + assertThat(config26DurationUs).isEqualTo(20_000); + assertThat(config27DurationUs).isEqualTo(40_000); + assertThat(config28DurationUs).isEqualTo(5_000); + assertThat(config29DurationUs).isEqualTo(10_000); + assertThat(config30DurationUs).isEqualTo(20_000); + assertThat(config31DurationUs).isEqualTo(40_000); + } + + @Test + public void getPacketDurationUs_code2_returnsExpectedDuration() { + long config0DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("06")); + long config1DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("0E")); + long config2DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("16")); + long config3DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("1E")); + long config4DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("26")); + long config5DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("2E")); + long config6DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("36")); + long config7DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("3E")); + long config8DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("46")); + long config9DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("4E")); + long config10DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("56")); + long config11DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("5E")); + long config12DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("66")); + long config13DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("6E")); + long config14DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("76")); + long config15DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("7E")); + long config16DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("86")); + long config17DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("8E")); + long config18DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("96")); + long config19DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("9E")); + long config20DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("A6")); + long config21DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("AE")); + long config22DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("B6")); + long config23DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("BE")); + long config24DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("C6")); + long config25DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("CE")); + long config26DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("D6")); + long config27DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("DE")); + long config28DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("E6")); + long config29DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("EE")); + long config30DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("F6")); + long config31DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("FE")); + + assertThat(config0DurationUs).isEqualTo(20_000); + assertThat(config1DurationUs).isEqualTo(40_000); + assertThat(config2DurationUs).isEqualTo(80_000); + assertThat(config3DurationUs).isEqualTo(120_000); + assertThat(config4DurationUs).isEqualTo(20_000); + assertThat(config5DurationUs).isEqualTo(40_000); + assertThat(config6DurationUs).isEqualTo(80_000); + assertThat(config7DurationUs).isEqualTo(120_000); + assertThat(config8DurationUs).isEqualTo(20_000); + assertThat(config9DurationUs).isEqualTo(40_000); + assertThat(config10DurationUs).isEqualTo(80_000); + assertThat(config11DurationUs).isEqualTo(120_000); + assertThat(config12DurationUs).isEqualTo(20_000); + assertThat(config13DurationUs).isEqualTo(40_000); + assertThat(config14DurationUs).isEqualTo(20_000); + assertThat(config15DurationUs).isEqualTo(40_000); + assertThat(config16DurationUs).isEqualTo(5_000); + assertThat(config17DurationUs).isEqualTo(10_000); + assertThat(config18DurationUs).isEqualTo(20_000); + assertThat(config19DurationUs).isEqualTo(40_000); + assertThat(config20DurationUs).isEqualTo(5_000); + assertThat(config21DurationUs).isEqualTo(10_000); + assertThat(config22DurationUs).isEqualTo(20_000); + assertThat(config23DurationUs).isEqualTo(40_000); + assertThat(config24DurationUs).isEqualTo(5_000); + assertThat(config25DurationUs).isEqualTo(10_000); + assertThat(config26DurationUs).isEqualTo(20_000); + assertThat(config27DurationUs).isEqualTo(40_000); + assertThat(config28DurationUs).isEqualTo(5_000); + assertThat(config29DurationUs).isEqualTo(10_000); + assertThat(config30DurationUs).isEqualTo(20_000); + assertThat(config31DurationUs).isEqualTo(40_000); + } + + @Test + public void getPacketDurationUs_code3_returnsExpectedDuration() { + // max possible frame count to reach 120ms duration + long config0DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("078C")); + long config1DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("0F86")); + long config2DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("1783")); + long config3DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("1F82")); + // frame count of 2 + long config4DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("2782")); + long config5DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("2F82")); + long config6DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("3782")); + long config7DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("3F82")); + long config8DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("4782")); + long config9DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("4F82")); + long config10DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("5782")); + long config11DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("5F82")); + // max possible frame count to reach 120ms duration + long config12DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("678C")); + long config13DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("6F86")); + // frame count of 2 + long config14DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("7782")); + long config15DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("7F82")); + // max possible frame count to reach 120ms duration + long config16DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("87B0")); + long config17DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("8F98")); + long config18DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("978C")); + long config19DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("9F86")); + // frame count of 2 + long config20DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("A782")); + long config21DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("AF82")); + long config22DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("B782")); + long config23DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("BF82")); + long config24DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("C782")); + long config25DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("CF82")); + long config26DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("D782")); + long config27DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("DF82")); + long config28DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("E782")); + long config29DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("EF82")); + long config30DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("F782")); + long config31DurationUs = OpusUtil.getPacketDurationUs(getBytesFromHexString("FF82")); + + assertThat(config0DurationUs).isEqualTo(120_000); + assertThat(config1DurationUs).isEqualTo(120_000); + assertThat(config2DurationUs).isEqualTo(120_000); + assertThat(config3DurationUs).isEqualTo(120_000); + assertThat(config4DurationUs).isEqualTo(20_000); + assertThat(config5DurationUs).isEqualTo(40_000); + assertThat(config6DurationUs).isEqualTo(80_000); + assertThat(config7DurationUs).isEqualTo(120_000); + assertThat(config8DurationUs).isEqualTo(20_000); + assertThat(config9DurationUs).isEqualTo(40_000); + assertThat(config10DurationUs).isEqualTo(80_000); + assertThat(config11DurationUs).isEqualTo(120_000); + assertThat(config12DurationUs).isEqualTo(120_000); + assertThat(config13DurationUs).isEqualTo(120_000); + assertThat(config14DurationUs).isEqualTo(20_000); + assertThat(config15DurationUs).isEqualTo(40_000); + assertThat(config16DurationUs).isEqualTo(120_000); + assertThat(config17DurationUs).isEqualTo(120_000); + assertThat(config18DurationUs).isEqualTo(120_000); + assertThat(config19DurationUs).isEqualTo(120_000); + assertThat(config20DurationUs).isEqualTo(5_000); + assertThat(config21DurationUs).isEqualTo(10_000); + assertThat(config22DurationUs).isEqualTo(20_000); + assertThat(config23DurationUs).isEqualTo(40_000); + assertThat(config24DurationUs).isEqualTo(5_000); + assertThat(config25DurationUs).isEqualTo(10_000); + assertThat(config26DurationUs).isEqualTo(20_000); + assertThat(config27DurationUs).isEqualTo(40_000); + assertThat(config28DurationUs).isEqualTo(5_000); + assertThat(config29DurationUs).isEqualTo(10_000); + assertThat(config30DurationUs).isEqualTo(20_000); + assertThat(config31DurationUs).isEqualTo(40_000); + } + + @Test + public void getPacketAudioSampleCount_code0_returnsExpectedDuration() { + int config0SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("04")); + int config1SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("0C")); + int config2SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("14")); + int config3SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("1C")); + int config4SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("24")); + int config5SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("2C")); + int config6SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("34")); + int config7SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("3C")); + int config8SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("44")); + int config9SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("4C")); + int config10SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("54")); + int config11SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("5C")); + int config12SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("64")); + int config13SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("6C")); + int config14SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("74")); + int config15SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("7C")); + int config16SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("84")); + int config17SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("8C")); + int config18SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("94")); + int config19SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("9C")); + int config20SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("A4")); + int config21SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("AC")); + int config22SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("B4")); + int config23SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("BC")); + int config24SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("C4")); + int config25SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("CC")); + int config26SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("D4")); + int config27SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("DC")); + int config28SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("E4")); + int config29SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("EC")); + int config30SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("F4")); + int config31SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("FC")); + + assertThat(config0SampleCount).isEqualTo(480); + assertThat(config1SampleCount).isEqualTo(960); + assertThat(config2SampleCount).isEqualTo(1920); + assertThat(config3SampleCount).isEqualTo(2880); + assertThat(config4SampleCount).isEqualTo(480); + assertThat(config5SampleCount).isEqualTo(960); + assertThat(config6SampleCount).isEqualTo(1920); + assertThat(config7SampleCount).isEqualTo(2880); + assertThat(config8SampleCount).isEqualTo(480); + assertThat(config9SampleCount).isEqualTo(960); + assertThat(config10SampleCount).isEqualTo(1920); + assertThat(config11SampleCount).isEqualTo(2880); + assertThat(config12SampleCount).isEqualTo(480); + assertThat(config13SampleCount).isEqualTo(960); + assertThat(config14SampleCount).isEqualTo(480); + assertThat(config15SampleCount).isEqualTo(960); + assertThat(config16SampleCount).isEqualTo(120); + assertThat(config17SampleCount).isEqualTo(240); + assertThat(config18SampleCount).isEqualTo(480); + assertThat(config19SampleCount).isEqualTo(960); + assertThat(config20SampleCount).isEqualTo(120); + assertThat(config21SampleCount).isEqualTo(240); + assertThat(config22SampleCount).isEqualTo(480); + assertThat(config23SampleCount).isEqualTo(960); + assertThat(config24SampleCount).isEqualTo(120); + assertThat(config25SampleCount).isEqualTo(240); + assertThat(config26SampleCount).isEqualTo(480); + assertThat(config27SampleCount).isEqualTo(960); + assertThat(config28SampleCount).isEqualTo(120); + assertThat(config29SampleCount).isEqualTo(240); + assertThat(config30SampleCount).isEqualTo(480); + assertThat(config31SampleCount).isEqualTo(960); + } + + @Test + public void getPacketAudioSampleCount_code1_returnsExpectedDuration() { + int config0SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("05")); + int config1SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("0D")); + int config2SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("15")); + int config3SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("1D")); + int config4SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("25")); + int config5SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("2D")); + int config6SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("35")); + int config7SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("3D")); + int config8SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("45")); + int config9SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("4D")); + int config10SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("55")); + int config11SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("5D")); + int config12SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("65")); + int config13SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("6D")); + int config14SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("75")); + int config15SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("7D")); + int config16SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("85")); + int config17SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("8D")); + int config18SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("95")); + int config19SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("9D")); + int config20SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("A5")); + int config21SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("AD")); + int config22SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("B5")); + int config23SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("BD")); + int config24SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("C5")); + int config25SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("CD")); + int config26SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("D5")); + int config27SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("DD")); + int config28SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("E5")); + int config29SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("ED")); + int config30SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("F5")); + int config31SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("FD")); + + assertThat(config0SampleCount).isEqualTo(960); + assertThat(config1SampleCount).isEqualTo(1920); + assertThat(config2SampleCount).isEqualTo(3840); + assertThat(config3SampleCount).isEqualTo(5760); + assertThat(config4SampleCount).isEqualTo(960); + assertThat(config5SampleCount).isEqualTo(1920); + assertThat(config6SampleCount).isEqualTo(3840); + assertThat(config7SampleCount).isEqualTo(5760); + assertThat(config8SampleCount).isEqualTo(960); + assertThat(config9SampleCount).isEqualTo(1920); + assertThat(config10SampleCount).isEqualTo(3840); + assertThat(config11SampleCount).isEqualTo(5760); + assertThat(config12SampleCount).isEqualTo(960); + assertThat(config13SampleCount).isEqualTo(1920); + assertThat(config14SampleCount).isEqualTo(960); + assertThat(config15SampleCount).isEqualTo(1920); + assertThat(config16SampleCount).isEqualTo(240); + assertThat(config17SampleCount).isEqualTo(480); + assertThat(config18SampleCount).isEqualTo(960); + assertThat(config19SampleCount).isEqualTo(1920); + assertThat(config20SampleCount).isEqualTo(240); + assertThat(config21SampleCount).isEqualTo(480); + assertThat(config22SampleCount).isEqualTo(960); + assertThat(config23SampleCount).isEqualTo(1920); + assertThat(config24SampleCount).isEqualTo(240); + assertThat(config25SampleCount).isEqualTo(480); + assertThat(config26SampleCount).isEqualTo(960); + assertThat(config27SampleCount).isEqualTo(1920); + assertThat(config28SampleCount).isEqualTo(240); + assertThat(config29SampleCount).isEqualTo(480); + assertThat(config30SampleCount).isEqualTo(960); + assertThat(config31SampleCount).isEqualTo(1920); + } + + @Test + public void getPacketAudioSampleCount_code2_returnsExpectedDuration() { + int config0SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("06")); + int config1SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("0E")); + int config2SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("16")); + int config3SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("1E")); + int config4SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("26")); + int config5SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("2E")); + int config6SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("36")); + int config7SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("3E")); + int config8SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("46")); + int config9SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("4E")); + int config10SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("56")); + int config11SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("5E")); + int config12SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("66")); + int config13SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("6E")); + int config14SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("76")); + int config15SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("7E")); + int config16SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("86")); + int config17SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("8E")); + int config18SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("96")); + int config19SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("9E")); + int config20SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("A6")); + int config21SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("AE")); + int config22SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("B6")); + int config23SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("BE")); + int config24SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("C6")); + int config25SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("CE")); + int config26SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("D6")); + int config27SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("DE")); + int config28SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("E6")); + int config29SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("EE")); + int config30SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("F6")); + int config31SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("FE")); + + assertThat(config0SampleCount).isEqualTo(960); + assertThat(config1SampleCount).isEqualTo(1920); + assertThat(config2SampleCount).isEqualTo(3840); + assertThat(config3SampleCount).isEqualTo(5760); + assertThat(config4SampleCount).isEqualTo(960); + assertThat(config5SampleCount).isEqualTo(1920); + assertThat(config6SampleCount).isEqualTo(3840); + assertThat(config7SampleCount).isEqualTo(5760); + assertThat(config8SampleCount).isEqualTo(960); + assertThat(config9SampleCount).isEqualTo(1920); + assertThat(config10SampleCount).isEqualTo(3840); + assertThat(config11SampleCount).isEqualTo(5760); + assertThat(config12SampleCount).isEqualTo(960); + assertThat(config13SampleCount).isEqualTo(1920); + assertThat(config14SampleCount).isEqualTo(960); + assertThat(config15SampleCount).isEqualTo(1920); + assertThat(config16SampleCount).isEqualTo(240); + assertThat(config17SampleCount).isEqualTo(480); + assertThat(config18SampleCount).isEqualTo(960); + assertThat(config19SampleCount).isEqualTo(1920); + assertThat(config20SampleCount).isEqualTo(240); + assertThat(config21SampleCount).isEqualTo(480); + assertThat(config22SampleCount).isEqualTo(960); + assertThat(config23SampleCount).isEqualTo(1920); + assertThat(config24SampleCount).isEqualTo(240); + assertThat(config25SampleCount).isEqualTo(480); + assertThat(config26SampleCount).isEqualTo(960); + assertThat(config27SampleCount).isEqualTo(1920); + assertThat(config28SampleCount).isEqualTo(240); + assertThat(config29SampleCount).isEqualTo(480); + assertThat(config30SampleCount).isEqualTo(960); + assertThat(config31SampleCount).isEqualTo(1920); + } + + @Test + public void getPacketAudioSampleCount_code3_returnsExpectedDuration() { + // max possible frame count to reach 120ms duration + int config0SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("078C")); + int config1SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("0F86")); + int config2SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("1783")); + int config3SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("1F82")); + // frame count of 2 + int config4SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("2782")); + int config5SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("2F82")); + int config6SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("3782")); + int config7SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("3F82")); + int config8SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("4782")); + int config9SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("4F82")); + int config10SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("5782")); + int config11SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("5F82")); + // max possible frame count to reach 120ms duration + int config12SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("678C")); + int config13SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("6F86")); + // frame count of 2 + int config14SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("7782")); + int config15SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("7F82")); + // max possible frame count to reach 120ms duration + int config16SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("87B0")); + int config17SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("8F98")); + int config18SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("978C")); + int config19SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("9F86")); + // frame count of 2 + int config20SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("A782")); + int config21SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("AF82")); + int config22SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("B782")); + int config23SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("BF82")); + int config24SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("C782")); + int config25SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("CF82")); + int config26SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("D782")); + int config27SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("DF82")); + int config28SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("E782")); + int config29SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("EF82")); + int config30SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("F782")); + int config31SampleCount = OpusUtil.parsePacketAudioSampleCount(getByteBuffer("FF82")); + + assertThat(config0SampleCount).isEqualTo(5760); + assertThat(config1SampleCount).isEqualTo(5760); + assertThat(config2SampleCount).isEqualTo(5760); + assertThat(config3SampleCount).isEqualTo(5760); + assertThat(config4SampleCount).isEqualTo(960); + assertThat(config5SampleCount).isEqualTo(1920); + assertThat(config6SampleCount).isEqualTo(3840); + assertThat(config7SampleCount).isEqualTo(5760); + assertThat(config8SampleCount).isEqualTo(960); + assertThat(config9SampleCount).isEqualTo(1920); + assertThat(config10SampleCount).isEqualTo(3840); + assertThat(config11SampleCount).isEqualTo(5760); + assertThat(config12SampleCount).isEqualTo(5760); + assertThat(config13SampleCount).isEqualTo(5760); + assertThat(config14SampleCount).isEqualTo(960); + assertThat(config15SampleCount).isEqualTo(1920); + assertThat(config16SampleCount).isEqualTo(5760); + assertThat(config17SampleCount).isEqualTo(5760); + assertThat(config18SampleCount).isEqualTo(5760); + assertThat(config19SampleCount).isEqualTo(5760); + assertThat(config20SampleCount).isEqualTo(240); + assertThat(config21SampleCount).isEqualTo(480); + assertThat(config22SampleCount).isEqualTo(960); + assertThat(config23SampleCount).isEqualTo(1920); + assertThat(config24SampleCount).isEqualTo(240); + assertThat(config25SampleCount).isEqualTo(480); + assertThat(config26SampleCount).isEqualTo(960); + assertThat(config27SampleCount).isEqualTo(1920); + assertThat(config28SampleCount).isEqualTo(240); + assertThat(config29SampleCount).isEqualTo(480); + assertThat(config30SampleCount).isEqualTo(960); + assertThat(config31SampleCount).isEqualTo(1920); + } + private static long sampleCountToNanoseconds(long sampleCount) { return (sampleCount * C.NANOS_PER_SECOND) / OpusUtil.SAMPLE_RATE; } @@ -62,4 +629,8 @@ public final class OpusUtilTest { private static byte[] buildNativeOrderByteArray(long value) { return ByteBuffer.allocate(8).order(ByteOrder.nativeOrder()).putLong(value).array(); } + + private static ByteBuffer getByteBuffer(String hexString) { + return ByteBuffer.wrap(getBytesFromHexString(hexString)); + } } From 9bd79ebdcdcf369874c2d4dc21f3eda89bee2dff Mon Sep 17 00:00:00 2001 From: kimvde Date: Tue, 29 Nov 2022 14:52:05 +0000 Subject: [PATCH 019/183] Move sample processing to transformer thread PiperOrigin-RevId: 491623586 --- .../transformer/BaseSamplePipeline.java | 7 - .../transformer/ExoPlayerAssetLoader.java | 15 +- .../ExoPlayerAssetLoaderRenderer.java | 33 ++-- .../exoplayer2/transformer/MuxerWrapper.java | 7 + .../transformer/SamplePipeline.java | 14 +- .../transformer/TransformerInternal.java | 165 +++++++++++++++--- 6 files changed, 177 insertions(+), 64 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java index 0789509573..170c1d6a82 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java @@ -39,7 +39,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; @Nullable private DecoderInputBuffer inputBuffer; private boolean muxerWrapperTrackAdded; - private boolean isEnded; public BaseSamplePipeline( Format inputFormat, @@ -81,11 +80,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; return feedMuxer() || processDataUpToMuxer(); } - @Override - public boolean isEnded() { - return isEnded; - } - @Nullable protected abstract DecoderInputBuffer dequeueInputBufferInternal() throws TransformationException; @@ -148,7 +142,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; if (isMuxerInputEnded()) { muxerWrapper.endTrack(trackType); - isEnded = true; return false; } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java index 7b2c326aab..58654427e2 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java @@ -20,7 +20,6 @@ import static com.google.android.exoplayer2.DefaultLoadControl.DEFAULT_BUFFER_FO import static com.google.android.exoplayer2.DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS; import static com.google.android.exoplayer2.DefaultLoadControl.DEFAULT_MAX_BUFFER_MS; import static com.google.android.exoplayer2.DefaultLoadControl.DEFAULT_MIN_BUFFER_MS; -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import android.content.Context; import android.os.Handler; @@ -55,11 +54,10 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; void onAllTracksRegistered(); - SamplePipeline onTrackAdded(Format format, long streamStartPositionUs, long streamOffsetUs) + SamplePipeline.Input onTrackAdded( + Format format, long streamStartPositionUs, long streamOffsetUs) throws TransformationException; - void onEnded(); - void onError(Exception e); } @@ -111,6 +109,7 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; public void start() { player.setMediaItem(mediaItem); player.prepare(); + player.play(); } public void release() { @@ -167,13 +166,6 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; this.listener = listener; } - @Override - public void onPlaybackStateChanged(int state) { - if (state == Player.STATE_ENDED) { - listener.onEnded(); - } - } - @Override public void onTimelineChanged(Timeline timeline, int reason) { if (hasSentDuration) { @@ -184,7 +176,6 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; if (!window.isPlaceholder) { listener.onDurationMs(Util.usToMs(window.durationUs)); hasSentDuration = true; - checkNotNull(player).play(); } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderRenderer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderRenderer.java index 951e373eea..919faa2474 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderRenderer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderRenderer.java @@ -45,7 +45,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; private boolean isTransformationRunning; private long streamStartPositionUs; private long streamOffsetUs; - private @MonotonicNonNull SamplePipeline samplePipeline; + private SamplePipeline.@MonotonicNonNull Input samplePipelineInput; + private boolean isEnded; public ExoPlayerAssetLoaderRenderer( int trackType, @@ -88,7 +89,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; @Override public boolean isEnded() { - return samplePipeline != null && samplePipeline.isEnded(); + return isEnded; } @Override @@ -98,7 +99,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; return; } - while (samplePipeline.processData() || feedPipelineFromInput()) {} + while (feedPipelineFromInput()) {} } catch (TransformationException e) { isTransformationRunning = false; assetLoaderListener.onError(e); @@ -127,16 +128,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; isTransformationRunning = false; } - @Override - protected void onReset() { - if (samplePipeline != null) { - samplePipeline.release(); - } - } - - @EnsuresNonNullIf(expression = "samplePipeline", result = true) + @EnsuresNonNullIf(expression = "samplePipelineInput", result = true) private boolean ensureConfigured() throws TransformationException { - if (samplePipeline != null) { + if (samplePipelineInput != null) { return true; } @@ -147,7 +141,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; return false; } Format inputFormat = checkNotNull(formatHolder.format); - samplePipeline = + samplePipelineInput = assetLoaderListener.onTrackAdded(inputFormat, streamStartPositionUs, streamOffsetUs); return true; } @@ -156,11 +150,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * Attempts to read input data and pass the input data to the sample pipeline. * * @return Whether it may be possible to read more data immediately by calling this method again. - * @throws TransformationException If a {@link SamplePipeline} problem occurs. */ - @RequiresNonNull("samplePipeline") - private boolean feedPipelineFromInput() throws TransformationException { - @Nullable DecoderInputBuffer samplePipelineInputBuffer = samplePipeline.dequeueInputBuffer(); + @RequiresNonNull("samplePipelineInput") + private boolean feedPipelineFromInput() { + @Nullable + DecoderInputBuffer samplePipelineInputBuffer = samplePipelineInput.dequeueInputBuffer(); if (samplePipelineInputBuffer == null) { return false; } @@ -171,11 +165,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; case C.RESULT_BUFFER_READ: samplePipelineInputBuffer.flip(); if (samplePipelineInputBuffer.isEndOfStream()) { - samplePipeline.queueInputBuffer(); + samplePipelineInput.queueInputBuffer(); + isEnded = true; return false; } mediaClock.updateTimeForTrackType(getTrackType(), samplePipelineInputBuffer.timeUs); - samplePipeline.queueInputBuffer(); + samplePipelineInput.queueInputBuffer(); return true; case C.RESULT_FORMAT_READ: throw new IllegalStateException("Format changes are not supported."); 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 f0ea1d2cbe..0c124cdf00 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 @@ -69,6 +69,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; private int trackCount; private int trackFormatCount; private boolean isReady; + private boolean isEnded; private @C.TrackType int previousTrackType; private long minTrackTimeUs; private @MonotonicNonNull ScheduledFuture abortScheduledFuture; @@ -216,9 +217,15 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; trackTypeToIndex.delete(trackType); if (trackTypeToIndex.size() == 0) { abortScheduledExecutorService.shutdownNow(); + isEnded = true; } } + /** Returns whether all the tracks are {@linkplain #endTrack(int) ended}. */ + public boolean isEnded() { + return isEnded; + } + /** * Finishes writing the output and releases any resources associated with muxing. * diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java index 2789c008f7..e789ce9149 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java @@ -26,6 +26,17 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; */ /* package */ interface SamplePipeline { + /** Input of a {@link SamplePipeline}. */ + interface Input { + + /** See {@link SamplePipeline#dequeueInputBuffer()}. */ + @Nullable + DecoderInputBuffer dequeueInputBuffer(); + + /** See {@link SamplePipeline#queueInputBuffer()}. */ + void queueInputBuffer(); + } + /** A listener for the sample pipeline events. */ interface Listener { @@ -63,9 +74,6 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; */ boolean processData() throws TransformationException; - /** Returns whether the pipeline has ended. */ - boolean isEnded(); - /** Releases all resources held by the pipeline. */ void release(); } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java index 3d4900eed0..358ac101e5 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java @@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STA import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE; import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_WAITING_FOR_AVAILABILITY; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; +import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; import static java.lang.Math.min; import static java.lang.annotation.ElementType.TYPE_USE; @@ -36,6 +37,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.audio.AudioProcessor; +import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.mp4.SlowMotionData; import com.google.android.exoplayer2.source.MediaSource; @@ -52,6 +54,8 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.ArrayList; +import java.util.List; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /* package */ final class TransformerInternal { @@ -81,7 +85,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; // Internal messages. private static final int MSG_START = 0; - private static final int MSG_END = 1; + private static final int MSG_REGISTER_SAMPLE_PIPELINE = 1; + private static final int MSG_DEQUEUE_INPUT = 2; + private static final int MSG_QUEUE_INPUT = 3; + private static final int MSG_DRAIN_PIPELINES = 4; + private static final int MSG_END = 5; + + private static final int DRAIN_PIPELINES_DELAY_MS = 10; private final Context context; private final TransformationRequest transformationRequest; @@ -97,15 +107,20 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private final HandlerThread internalHandlerThread; private final HandlerWrapper internalHandler; private final ExoPlayerAssetLoader exoPlayerAssetLoader; + private final List samplePipelines; + private final ConditionVariable dequeueBufferConditionVariable; private final MuxerWrapper muxerWrapper; private final ConditionVariable cancellingConditionVariable; + @Nullable private DecoderInputBuffer pendingInputBuffer; + private boolean isDrainingPipelines; private @Transformer.ProgressState int progressState; private long progressPositionMs; private long durationMs; - private boolean released; private @MonotonicNonNull RuntimeException cancelException; + private volatile boolean released; + public TransformerInternal( Context context, MediaItem mediaItem, @@ -151,6 +166,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; internalLooper, componentListener, clock); + samplePipelines = new ArrayList<>(); + dequeueBufferConditionVariable = new ConditionVariable(); muxerWrapper = new MuxerWrapper( outputPath, @@ -190,11 +207,27 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } private boolean handleMessage(Message msg) { + // Handle end messages even if resources have been released to report release timeouts. + if (released && msg.what != MSG_END) { + return true; + } try { switch (msg.what) { case MSG_START: startInternal(); break; + case MSG_REGISTER_SAMPLE_PIPELINE: + samplePipelines.add((SamplePipeline) msg.obj); + break; + case MSG_DEQUEUE_INPUT: + dequeueInputInternal(/* samplePipelineIndex= */ msg.arg1); + break; + case MSG_QUEUE_INPUT: + queueInputInternal(/* samplePipelineIndex= */ msg.arg1); + break; + case MSG_DRAIN_PIPELINES: + drainPipelinesInternal(); + break; case MSG_END: endInternal( /* endReason= */ msg.arg1, @@ -203,6 +236,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; default: return false; } + } catch (TransformationException e) { + endInternal(END_REASON_ERROR, e); } catch (RuntimeException e) { endInternal(END_REASON_ERROR, TransformationException.createForUnexpected(e)); } @@ -213,6 +248,41 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; exoPlayerAssetLoader.start(); } + private void dequeueInputInternal(int samplePipelineIndex) throws TransformationException { + SamplePipeline samplePipeline = samplePipelines.get(samplePipelineIndex); + // The sample pipeline is drained before dequeuing input. It can't be done before queuing + // input because, if the pipeline is full, dequeuing input would forever return a null buffer. + // Draining the pipeline at regular intervals would be inefficient because a low interval could + // result in many no-op operations, and a high interval could slow down data queuing. + while (samplePipeline.processData()) {} + pendingInputBuffer = samplePipeline.dequeueInputBuffer(); + dequeueBufferConditionVariable.open(); + } + + private void queueInputInternal(int samplePipelineIndex) throws TransformationException { + DecoderInputBuffer pendingInputBuffer = checkStateNotNull(this.pendingInputBuffer); + samplePipelines.get(samplePipelineIndex).queueInputBuffer(); + if (pendingInputBuffer.isEndOfStream() && !isDrainingPipelines) { + internalHandler.sendEmptyMessageDelayed(MSG_DRAIN_PIPELINES, DRAIN_PIPELINES_DELAY_MS); + isDrainingPipelines = true; + } + } + + private void drainPipelinesInternal() throws TransformationException { + for (int i = 0; i < samplePipelines.size(); i++) { + while (samplePipelines.get(i).processData()) {} + } + + if (muxerWrapper.isEnded()) { + internalHandler + .obtainMessage( + MSG_END, END_REASON_COMPLETED, /* unused */ 0, /* transformationException */ null) + .sendToTarget(); + } else { + internalHandler.sendEmptyMessageDelayed(MSG_DRAIN_PIPELINES, DRAIN_PIPELINES_DELAY_MS); + } + } + private void endInternal( @EndReason int endReason, @Nullable TransformationException transformationException) { @Nullable TransformationResult transformationResult = null; @@ -220,21 +290,34 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Nullable TransformationException releaseTransformationException = null; if (!released) { released = true; + + // Make sure there is no dequeue action waiting on the asset loader thread to avoid a + // deadlock when releasing it. + pendingInputBuffer = null; + dequeueBufferConditionVariable.open(); try { try { exoPlayerAssetLoader.release(); - if (endReason == END_REASON_COMPLETED) { - transformationResult = - new TransformationResult.Builder() - .setDurationMs(checkNotNull(muxerWrapper).getDurationMs()) - .setAverageAudioBitrate(muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_AUDIO)) - .setAverageVideoBitrate(muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_VIDEO)) - .setVideoFrameCount(muxerWrapper.getTrackSampleCount(C.TRACK_TYPE_VIDEO)) - .setFileSizeBytes(muxerWrapper.getCurrentOutputSizeBytes()) - .build(); - } } finally { - muxerWrapper.release(forCancellation); + try { + for (int i = 0; i < samplePipelines.size(); i++) { + samplePipelines.get(i).release(); + } + if (endReason == END_REASON_COMPLETED) { + transformationResult = + new TransformationResult.Builder() + .setDurationMs(checkNotNull(muxerWrapper).getDurationMs()) + .setAverageAudioBitrate( + muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_AUDIO)) + .setAverageVideoBitrate( + muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_VIDEO)) + .setVideoFrameCount(muxerWrapper.getTrackSampleCount(C.TRACK_TYPE_VIDEO)) + .setFileSizeBytes(muxerWrapper.getCurrentOutputSizeBytes()) + .build(); + } + } finally { + muxerWrapper.release(forCancellation); + } } } catch (Muxer.MuxerException e) { releaseTransformationException = @@ -273,6 +356,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private final MediaItem mediaItem; private final FallbackListener fallbackListener; + + private int tracksAddedCount; private long lastProgressUpdateMs; private long lastProgressPositionMs; @@ -315,10 +400,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } @Override - public SamplePipeline onTrackAdded( + public SamplePipeline.Input onTrackAdded( Format format, long streamStartPositionUs, long streamOffsetUs) throws TransformationException { - return getSamplePipeline(format, streamStartPositionUs, streamOffsetUs); + SamplePipeline samplePipeline = + getSamplePipeline(format, streamStartPositionUs, streamOffsetUs); + internalHandler.obtainMessage(MSG_REGISTER_SAMPLE_PIPELINE, samplePipeline).sendToTarget(); + + int samplePipelineIndex = tracksAddedCount; + tracksAddedCount++; + return new SamplePipelineInput(samplePipelineIndex); } @Override @@ -335,14 +426,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; onTransformationError(transformationException); } - @Override - public void onEnded() { - internalHandler - .obtainMessage( - MSG_END, END_REASON_COMPLETED, /* unused */ 0, /* transformationException */ null) - .sendToTarget(); - } - // SamplePipeline.Listener implementation. @Override @@ -486,5 +569,41 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } return false; } + + private class SamplePipelineInput implements SamplePipeline.Input { + + private final int samplePipelineIndex; + + public SamplePipelineInput(int samplePipelineIndex) { + this.samplePipelineIndex = samplePipelineIndex; + } + + @Nullable + @Override + public DecoderInputBuffer dequeueInputBuffer() { + if (released) { + // Make sure there is no dequeue action waiting on the asset loader thread when it is + // being released to avoid a deadlock. + return null; + } + // TODO(b/252537210): Reduce the number of thread hops (for example by adding a queue at the + // start of thesample pipelines). Having 2 thread hops per sample (one for dequeuing and + // one for queuing) makes transmuxing slower than it used to be. + internalHandler + .obtainMessage(MSG_DEQUEUE_INPUT, samplePipelineIndex, /* unused */ 0) + .sendToTarget(); + clock.onThreadBlocked(); + dequeueBufferConditionVariable.blockUninterruptible(); + dequeueBufferConditionVariable.close(); + return pendingInputBuffer; + } + + @Override + public void queueInputBuffer() { + internalHandler + .obtainMessage(MSG_QUEUE_INPUT, samplePipelineIndex, /* unused */ 0) + .sendToTarget(); + } + } } } From e219ac21ae604f182769d69f6f590191a92100d0 Mon Sep 17 00:00:00 2001 From: christosts Date: Tue, 29 Nov 2022 15:18:11 +0000 Subject: [PATCH 020/183] Use audio bitrate to calculate AudioTrack min buffer in passthrough Use the bitrate of the audio format (when available) in DefaultAudioSink.AudioTrackBufferSizeProvider.getBufferSizeInBytes() to calculate accurate buffer sizes for direct (passthrough) playbacks. #minor-release PiperOrigin-RevId: 491628530 --- .../exoplayer2/audio/DefaultAudioSink.java | 4 ++ .../DefaultAudioTrackBufferSizeProvider.java | 23 +++++++--- ...ltAudioTrackBufferSizeProviderAC3Test.java | 21 ++++++++- ...dioTrackBufferSizeProviderEncodedTest.java | 43 +++++++++++++++++++ ...ltAudioTrackBufferSizeProviderPcmTest.java | 9 ++++ 5 files changed, 93 insertions(+), 7 deletions(-) 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 678863e2c9..fd22fdb968 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 @@ -190,6 +190,8 @@ public final class DefaultAudioSink implements AudioSink { * @param pcmFrameSize The size of the PCM frames if the {@code encoding} is PCM, 1 otherwise, * in bytes. * @param sampleRate The sample rate of the format, in Hz. + * @param bitrate The bitrate of the audio stream if the stream is compressed, or {@link + * Format#NO_VALUE} if {@code encoding} is PCM or the bitrate is not known. * @param maxAudioTrackPlaybackSpeed The maximum speed the content will be played using {@link * AudioTrack#setPlaybackParams}. 0.5 is 2x slow motion, 1 is real time, 2 is 2x fast * forward, etc. This will be {@code 1} unless {@link @@ -204,6 +206,7 @@ public final class DefaultAudioSink implements AudioSink { @OutputMode int outputMode, int pcmFrameSize, int sampleRate, + int bitrate, double maxAudioTrackPlaybackSpeed); } @@ -699,6 +702,7 @@ public final class DefaultAudioSink implements AudioSink { outputMode, outputPcmFrameSize != C.LENGTH_UNSET ? outputPcmFrameSize : 1, outputSampleRate, + inputFormat.bitrate, enableAudioTrackPlaybackParams ? MAX_PLAYBACK_SPEED : DEFAULT_PLAYBACK_SPEED); offloadDisabledUntilNextConfiguration = false; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProvider.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProvider.java index c9cc38fd53..2e774551fa 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProvider.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProvider.java @@ -19,6 +19,7 @@ import static com.google.android.exoplayer2.audio.DefaultAudioSink.OUTPUT_MODE_O import static com.google.android.exoplayer2.audio.DefaultAudioSink.OUTPUT_MODE_PASSTHROUGH; import static com.google.android.exoplayer2.audio.DefaultAudioSink.OUTPUT_MODE_PCM; import static com.google.android.exoplayer2.util.Util.constrainValue; +import static com.google.common.math.IntMath.divide; import static com.google.common.primitives.Ints.checkedCast; import static java.lang.Math.max; @@ -27,6 +28,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.audio.DefaultAudioSink.OutputMode; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import java.math.RoundingMode; /** Provide the buffer size to use when creating an {@link AudioTrack}. */ public class DefaultAudioTrackBufferSizeProvider @@ -166,10 +168,11 @@ public class DefaultAudioTrackBufferSizeProvider @OutputMode int outputMode, int pcmFrameSize, int sampleRate, + int bitrate, double maxAudioTrackPlaybackSpeed) { int bufferSize = get1xBufferSizeInBytes( - minBufferSizeInBytes, encoding, outputMode, pcmFrameSize, sampleRate); + minBufferSizeInBytes, encoding, outputMode, pcmFrameSize, sampleRate, bitrate); // Maintain the buffer duration by scaling the size accordingly. bufferSize = (int) (bufferSize * maxAudioTrackPlaybackSpeed); // Buffer size must not be lower than the AudioTrack min buffer size for this format. @@ -180,12 +183,17 @@ public class DefaultAudioTrackBufferSizeProvider /** Returns the buffer size for playback at 1x speed. */ protected int get1xBufferSizeInBytes( - int minBufferSizeInBytes, int encoding, int outputMode, int pcmFrameSize, int sampleRate) { + int minBufferSizeInBytes, + int encoding, + int outputMode, + int pcmFrameSize, + int sampleRate, + int bitrate) { switch (outputMode) { case OUTPUT_MODE_PCM: return getPcmBufferSizeInBytes(minBufferSizeInBytes, sampleRate, pcmFrameSize); case OUTPUT_MODE_PASSTHROUGH: - return getPassthroughBufferSizeInBytes(encoding); + return getPassthroughBufferSizeInBytes(encoding, bitrate); case OUTPUT_MODE_OFFLOAD: return getOffloadBufferSizeInBytes(encoding); default: @@ -202,13 +210,16 @@ public class DefaultAudioTrackBufferSizeProvider } /** Returns the buffer size for passthrough playback. */ - protected int getPassthroughBufferSizeInBytes(@C.Encoding int encoding) { + protected int getPassthroughBufferSizeInBytes(@C.Encoding int encoding, int bitrate) { int bufferSizeUs = passthroughBufferDurationUs; if (encoding == C.ENCODING_AC3) { bufferSizeUs *= ac3BufferMultiplicationFactor; } - int maxByteRate = getMaximumEncodedRateBytesPerSecond(encoding); - return checkedCast((long) bufferSizeUs * maxByteRate / C.MICROS_PER_SECOND); + int byteRate = + bitrate != Format.NO_VALUE + ? divide(bitrate, 8, RoundingMode.CEILING) + : getMaximumEncodedRateBytesPerSecond(encoding); + return checkedCast((long) bufferSizeUs * byteRate / C.MICROS_PER_SECOND); } /** Returns the buffer size for offload playback. */ diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderAC3Test.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderAC3Test.java index f282f1684e..d93bcaac26 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderAC3Test.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderAC3Test.java @@ -22,6 +22,7 @@ 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.Format; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,7 +35,7 @@ public class DefaultAudioTrackBufferSizeProviderAC3Test { @Test public void - getBufferSizeInBytes_passthroughAC3_isPassthroughBufferSizeTimesMultiplicationFactor() { + getBufferSizeInBytes_passthroughAc3AndNoBitrate_assumesMaxByteRateTimesMultiplicationFactor() { int bufferSize = DEFAULT.getBufferSizeInBytes( /* minBufferSizeInBytes= */ 0, @@ -42,6 +43,7 @@ public class DefaultAudioTrackBufferSizeProviderAC3Test { /* outputMode= */ OUTPUT_MODE_PASSTHROUGH, /* pcmFrameSize= */ 1, /* sampleRate= */ 0, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 1); assertThat(bufferSize) @@ -50,6 +52,23 @@ public class DefaultAudioTrackBufferSizeProviderAC3Test { * DEFAULT.ac3BufferMultiplicationFactor); } + @Test + public void + getBufferSizeInBytes_passthroughAC3At256Kbits_isPassthroughBufferSizeTimesMultiplicationFactor() { + int bufferSize = + DEFAULT.getBufferSizeInBytes( + /* minBufferSizeInBytes= */ 0, + /* encoding= */ C.ENCODING_AC3, + /* outputMode= */ OUTPUT_MODE_PASSTHROUGH, + /* pcmFrameSize= */ 1, + /* sampleRate= */ 0, + /* bitrate= */ 256_000, + /* maxAudioTrackPlaybackSpeed= */ 1); + + // Default buffer duration 0.25s => 0.25 * 256000 / 8 = 8000 + assertThat(bufferSize).isEqualTo(8000 * DEFAULT.ac3BufferMultiplicationFactor); + } + private static int durationUsToAc3MaxBytes(long durationUs) { return (int) (durationUs * getMaximumEncodedRateBytesPerSecond(C.ENCODING_AC3) / MICROS_PER_SECOND); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderEncodedTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderEncodedTest.java index 30db87083d..9d3a7e40a8 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderEncodedTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderEncodedTest.java @@ -15,10 +15,13 @@ */ package com.google.android.exoplayer2.audio; +import static com.google.android.exoplayer2.C.MICROS_PER_SECOND; import static com.google.android.exoplayer2.audio.DefaultAudioSink.OUTPUT_MODE_PASSTHROUGH; +import static com.google.android.exoplayer2.audio.DefaultAudioTrackBufferSizeProvider.getMaximumEncodedRateBytesPerSecond; import static com.google.common.truth.Truth.assertThat; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.Format; import com.google.common.collect.ImmutableList; import org.junit.Test; import org.junit.runner.RunWith; @@ -43,6 +46,8 @@ public class DefaultAudioTrackBufferSizeProviderEncodedTest { C.ENCODING_MP3, C.ENCODING_AAC_LC, C.ENCODING_AAC_HE_V1, + C.ENCODING_E_AC3, + C.ENCODING_E_AC3_JOC, C.ENCODING_AC4, C.ENCODING_DTS, C.ENCODING_DOLBY_TRUEHD); @@ -57,8 +62,46 @@ public class DefaultAudioTrackBufferSizeProviderEncodedTest { /* outputMode= */ OUTPUT_MODE_PASSTHROUGH, /* pcmFrameSize= */ 1, /* sampleRate= */ 0, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 0); assertThat(bufferSize).isEqualTo(123456789); } + + @Test + public void + getBufferSizeInBytes_passThroughAndBitrateNotSet_returnsBufferSizeWithAssumedBitrate() { + int bufferSize = + DEFAULT.getBufferSizeInBytes( + /* minBufferSizeInBytes= */ 0, + /* encoding= */ encoding, + /* outputMode= */ OUTPUT_MODE_PASSTHROUGH, + /* pcmFrameSize= */ 1, + /* sampleRate= */ 0, + /* bitrate= */ Format.NO_VALUE, + /* maxAudioTrackPlaybackSpeed= */ 1); + + assertThat(bufferSize) + .isEqualTo(durationUsToMaxBytes(encoding, DEFAULT.passthroughBufferDurationUs)); + } + + @Test + public void getBufferSizeInBytes_passthroughAndBitrateDefined() { + int bufferSize = + DEFAULT.getBufferSizeInBytes( + /* minBufferSizeInBytes= */ 0, + /* encoding= */ encoding, + /* outputMode= */ OUTPUT_MODE_PASSTHROUGH, + /* pcmFrameSize= */ 1, + /* sampleRate= */ 0, + /* bitrate= */ 256_000, + /* maxAudioTrackPlaybackSpeed= */ 1); + + // Default buffer duration is 250ms => 0.25 * 256000 / 8 = 8000 + assertThat(bufferSize).isEqualTo(8000); + } + + private static int durationUsToMaxBytes(@C.Encoding int encoding, long durationUs) { + return (int) (durationUs * getMaximumEncodedRateBytesPerSecond(encoding) / MICROS_PER_SECOND); + } } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderPcmTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderPcmTest.java index 06c0257548..293e14cf5f 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderPcmTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioTrackBufferSizeProviderPcmTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.lang.Math.ceil; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.Util; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -89,6 +90,7 @@ public class DefaultAudioTrackBufferSizeProviderPcmTest { /* outputMode= */ OUTPUT_MODE_PCM, /* pcmFrameSize= */ getPcmFrameSize(), /* sampleRate= */ sampleRate, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 1); assertThat(bufferSize).isEqualTo(roundUpToFrame(1234567890)); @@ -103,6 +105,7 @@ public class DefaultAudioTrackBufferSizeProviderPcmTest { /* outputMode= */ OUTPUT_MODE_PCM, /* pcmFrameSize= */ getPcmFrameSize(), /* sampleRate= */ sampleRate, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 1); assertThat(bufferSize) @@ -121,6 +124,7 @@ public class DefaultAudioTrackBufferSizeProviderPcmTest { /* outputMode= */ OUTPUT_MODE_PCM, /* pcmFrameSize= */ getPcmFrameSize(), /* sampleRate= */ sampleRate, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 1); assertThat(bufferSize) @@ -139,6 +143,7 @@ public class DefaultAudioTrackBufferSizeProviderPcmTest { /* outputMode= */ OUTPUT_MODE_PCM, /* pcmFrameSize= */ getPcmFrameSize(), /* sampleRate= */ sampleRate, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 1); assertThat(bufferSize) @@ -157,6 +162,7 @@ public class DefaultAudioTrackBufferSizeProviderPcmTest { /* outputMode= */ OUTPUT_MODE_PCM, /* pcmFrameSize= */ getPcmFrameSize(), /* sampleRate= */ sampleRate, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 1); assertThat(bufferSize) @@ -175,6 +181,7 @@ public class DefaultAudioTrackBufferSizeProviderPcmTest { /* outputMode= */ OUTPUT_MODE_PCM, /* pcmFrameSize= */ getPcmFrameSize(), /* sampleRate= */ sampleRate, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 1); assertThat(bufferSize) @@ -190,6 +197,7 @@ public class DefaultAudioTrackBufferSizeProviderPcmTest { /* outputMode= */ OUTPUT_MODE_PCM, /* pcmFrameSize= */ getPcmFrameSize(), /* sampleRate= */ sampleRate, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 1 / 5F); assertThat(bufferSize) @@ -205,6 +213,7 @@ public class DefaultAudioTrackBufferSizeProviderPcmTest { /* outputMode= */ OUTPUT_MODE_PCM, /* pcmFrameSize= */ getPcmFrameSize(), /* sampleRate= */ sampleRate, + /* bitrate= */ Format.NO_VALUE, /* maxAudioTrackPlaybackSpeed= */ 8F); int expected = roundUpToFrame(durationUsToBytes(DEFAULT.minPcmBufferDurationUs) * 8); From 18280723be60903945088df4e3c80a25eb55a6e6 Mon Sep 17 00:00:00 2001 From: claincly Date: Tue, 29 Nov 2022 17:35:55 +0000 Subject: [PATCH 021/183] Move audio MIME type fallback away to ATSP PiperOrigin-RevId: 491660842 --- .../transformer/AndroidTestUtil.java | 6 +-- .../TransformerAndroidTestRunner.java | 6 +-- .../transformer/TransformerEndToEndTest.java | 6 +-- .../AudioTranscodingSamplePipeline.java | 43 ++++++++++++++++--- .../transformer/BaseSamplePipeline.java | 11 +++++ .../android/exoplayer2/transformer/Codec.java | 19 ++++---- .../transformer/DefaultEncoderFactory.java | 15 +------ .../exoplayer2/transformer/EncoderUtil.java | 4 +- .../VideoTranscodingSamplePipeline.java | 8 +--- .../transformer/TransformerEndToEndTest.java | 21 ++++++--- .../transformer/VideoEncoderWrapperTest.java | 3 +- 11 files changed, 81 insertions(+), 61 deletions(-) diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java index 21d3a5473c..b1d53acfc9 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java @@ -36,7 +36,6 @@ import com.google.common.collect.ImmutableList; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.util.List; import org.json.JSONException; import org.json.JSONObject; @@ -472,9 +471,8 @@ public final class AndroidTestUtil { } @Override - public Codec createForAudioEncoding(Format format, List allowedMimeTypes) - throws TransformationException { - return encoderFactory.createForAudioEncoding(format, allowedMimeTypes); + public Codec createForAudioEncoding(Format format) throws TransformationException { + return encoderFactory.createForAudioEncoding(format); } @Override diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java index f6edebc7eb..8f54f7989a 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java @@ -35,7 +35,6 @@ import com.google.common.base.Ascii; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.io.File; import java.io.IOException; -import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeoutException; @@ -446,9 +445,8 @@ public class TransformerAndroidTestRunner { } @Override - public Codec createForAudioEncoding(Format format, List allowedMimeTypes) - throws TransformationException { - Codec audioEncoder = encoderFactory.createForAudioEncoding(format, allowedMimeTypes); + public Codec createForAudioEncoding(Format format) throws TransformationException { + Codec audioEncoder = encoderFactory.createForAudioEncoding(format); audioEncoderName = audioEncoder.getName(); return audioEncoder; } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index 55ce1bfb30..4f15e6b894 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -26,7 +26,6 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; -import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -140,9 +139,8 @@ public class TransformerEndToEndTest { } @Override - public Codec createForAudioEncoding(Format format, List allowedMimeTypes) - throws TransformationException { - return encoderFactory.createForAudioEncoding(format, allowedMimeTypes); + public Codec createForAudioEncoding(Format format) throws TransformationException { + return encoderFactory.createForAudioEncoding(format); } @Override diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java index 24db2537c6..b6aada7114 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java @@ -31,6 +31,7 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.util.Util; import com.google.common.collect.ImmutableList; import java.nio.ByteBuffer; +import java.util.List; import org.checkerframework.dataflow.qual.Pure; /** @@ -103,20 +104,33 @@ import org.checkerframework.dataflow.qual.Pure; audioProcessingPipeline.flush(); + String requestedMimeType = + transformationRequest.audioMimeType != null + ? transformationRequest.audioMimeType + : checkNotNull(inputFormat.sampleMimeType); Format requestedOutputFormat = new Format.Builder() - .setSampleMimeType( - transformationRequest.audioMimeType == null - ? inputFormat.sampleMimeType - : transformationRequest.audioMimeType) + .setSampleMimeType(requestedMimeType) .setSampleRate(encoderInputAudioFormat.sampleRate) .setChannelCount(encoderInputAudioFormat.channelCount) .setAverageBitrate(DEFAULT_ENCODER_BITRATE) .build(); + + ImmutableList muxerSupportedMimeTypes = + muxerWrapper.getSupportedSampleMimeTypes(C.TRACK_TYPE_AUDIO); + + // TODO(b/259570024): investigate overhauling fallback. + @Nullable + String supportedMimeType = + selectEncoderAndMuxerSupportedMimeType(requestedMimeType, muxerSupportedMimeTypes); + if (supportedMimeType == null) { + throw createNoSupportedMimeTypeException(requestedOutputFormat); + } + encoder = encoderFactory.createForAudioEncoding( - requestedOutputFormat, muxerWrapper.getSupportedSampleMimeTypes(C.TRACK_TYPE_AUDIO)); - + requestedOutputFormat.buildUpon().setSampleMimeType(supportedMimeType).build()); + checkState(supportedMimeType.equals(encoder.getConfigurationFormat().sampleMimeType)); fallbackListener.onTransformationRequestFinalized( createFallbackTransformationRequest( transformationRequest, requestedOutputFormat, encoder.getConfigurationFormat())); @@ -284,6 +298,23 @@ import org.checkerframework.dataflow.qual.Pure; encoder.queueInputBuffer(encoderInputBuffer); } + @Nullable + private static String selectEncoderAndMuxerSupportedMimeType( + String requestedMimeType, List muxerSupportedMimeTypes) { + if (!EncoderUtil.getSupportedEncoders(requestedMimeType).isEmpty()) { + return requestedMimeType; + } else { + // No encoder supports the requested MIME type. + for (int i = 0; i < muxerSupportedMimeTypes.size(); i++) { + String mimeType = muxerSupportedMimeTypes.get(i); + if (!EncoderUtil.getSupportedEncoders(mimeType).isEmpty()) { + return mimeType; + } + } + } + return null; + } + @Pure private static TransformationRequest createFallbackTransformationRequest( TransformationRequest transformationRequest, Format requestedFormat, Format actualFormat) { diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java index 170c1d6a82..ae1f4bdc09 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java @@ -58,6 +58,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; : null; } + protected static TransformationException createNoSupportedMimeTypeException( + Format requestedEncoderFormat) { + return TransformationException.createForCodec( + new IllegalArgumentException("No MIME type is supported by both encoder and muxer."), + MimeTypes.isVideo(requestedEncoderFormat.sampleMimeType), + /* isDecoder= */ false, + requestedEncoderFormat, + /* mediaCodecName= */ null, + TransformationException.ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED); + } + @Nullable @Override public DecoderInputBuffer dequeueInputBuffer() throws TransformationException { diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java index 9b5d209283..804194c260 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java @@ -22,9 +22,7 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; -import com.google.android.exoplayer2.util.MimeTypes; import java.nio.ByteBuffer; -import java.util.List; /** * Provides a layer of abstraction for interacting with decoders and encoders. @@ -70,19 +68,18 @@ public interface Codec { /** * Returns a {@link Codec} for audio encoding. * - *

This method must validate that the {@link Codec} is configured to produce one of the - * {@code allowedMimeTypes}. The {@linkplain Format#sampleMimeType sample MIME type} given in - * {@code format} is not necessarily allowed. + *

The caller should ensure the {@linkplain Format#sampleMimeType MIME type} is supported on + * the device before calling this method. * * @param format The {@link Format} (of the output data) used to determine the underlying - * encoder and its configuration values. - * @param allowedMimeTypes The non-empty list of allowed output sample {@linkplain MimeTypes - * MIME types}. - * @return A {@link Codec} for audio encoding. + * encoder and its configuration values. {@link Format#sampleMimeType}, {@link + * Format#sampleRate}, {@link Format#channelCount} and {@link Format#bitrate} are set to + * those of the desired output video format. + * @return A {@link Codec} for encoding audio to the requested {@link Format#sampleMimeType MIME + * type}. * @throws TransformationException If no suitable {@link Codec} can be created. */ - Codec createForAudioEncoding(Format format, List allowedMimeTypes) - throws TransformationException; + Codec createForAudioEncoding(Format format) throws TransformationException; /** * Returns a {@link Codec} for video encoding. diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java index 4dbcb397f5..f6f3b62cbd 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java @@ -172,23 +172,12 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { } @Override - public Codec createForAudioEncoding(Format format, List allowedMimeTypes) - throws TransformationException { + public DefaultCodec createForAudioEncoding(Format format) throws TransformationException { // TODO(b/210591626) Add encoder selection for audio. - checkArgument(!allowedMimeTypes.isEmpty()); checkNotNull(format.sampleMimeType); - if (!allowedMimeTypes.contains(format.sampleMimeType)) { - if (enableFallback) { - // TODO(b/210591626): Pick fallback MIME type using same strategy as for encoder - // capabilities limitations. - format = format.buildUpon().setSampleMimeType(allowedMimeTypes.get(0)).build(); - } else { - throw createTransformationException(format); - } - } MediaFormat mediaFormat = MediaFormat.createAudioFormat( - checkNotNull(format.sampleMimeType), format.sampleRate, format.channelCount); + format.sampleMimeType, format.sampleRate, format.channelCount); mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, format.bitrate); @Nullable diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java index dc1126b7ec..ee422166cd 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java @@ -444,9 +444,7 @@ public final class EncoderUtil { } String[] supportedMimeTypes = mediaCodecInfo.getSupportedTypes(); for (String mimeType : supportedMimeTypes) { - if (MimeTypes.isVideo(mimeType)) { - encoderInfosBuilder.put(Ascii.toLowerCase(mimeType), mediaCodecInfo); - } + encoderInfosBuilder.put(Ascii.toLowerCase(mimeType), mediaCodecInfo); } } return encoderInfosBuilder.build(); diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java index 9dfd6f0589..79f78b429d 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java @@ -461,13 +461,7 @@ import org.checkerframework.dataflow.qual.Pure; selectEncoderAndMuxerSupportedMimeType( requestedOutputMimeType, muxerSupportedMimeTypes, requestedEncoderFormat.colorInfo); if (supportedMimeType == null) { - throw TransformationException.createForCodec( - new IllegalArgumentException("No MIME type is supported by both encoder and muxer."), - /* isVideo= */ true, - /* isDecoder= */ false, - requestedEncoderFormat, - /* mediaCodecName= */ null, - TransformationException.ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED); + throw createNoSupportedMimeTypeException(requestedEncoderFormat); } encoder = diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index 0cada82975..0a16ff5b61 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -453,18 +453,25 @@ public final class TransformerEndToEndTest { } @Test - public void startTransformation_withAudioMuxerFormatUnsupported_completesWithError() + public void startTransformation_withAudioMuxerFormatUnsupported_completesSuccessfully() throws Exception { - Transformer transformer = createTransformerBuilder(/* enableFallback= */ false).build(); + // Test succeeds because MIME type fallback is mandatory. + Transformer.Listener mockListener = mock(Transformer.Listener.class); + TransformationRequest originalTransformationRequest = + new TransformationRequest.Builder().build(); + TransformationRequest fallbackTransformationRequest = + new TransformationRequest.Builder().setAudioMimeType(MimeTypes.AUDIO_AAC).build(); + Transformer transformer = + createTransformerBuilder(/* enableFallback= */ false).addListener(mockListener).build(); MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_UNSUPPORTED_BY_MUXER); transformer.startTransformation(mediaItem, outputPath); - TransformationException exception = TransformerTestRunner.runUntilError(transformer); + TransformerTestRunner.runUntilCompleted(transformer); - assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); - assertThat(exception).hasMessageThat().contains("audio"); - assertThat(exception.errorCode) - .isEqualTo(TransformationException.ERROR_CODE_OUTPUT_FORMAT_UNSUPPORTED); + DumpFileAsserts.assertOutput( + context, testMuxer, getDumpFileName(FILE_AUDIO_UNSUPPORTED_BY_MUXER + ".fallback")); + verify(mockListener) + .onFallbackApplied(mediaItem, originalTransformationRequest, fallbackTransformationRequest); } @Test diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java index 9fc8a231ff..f187aa370c 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java @@ -32,7 +32,6 @@ import com.google.android.exoplayer2.util.ListenerSet; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.SurfaceInfo; import com.google.common.collect.ImmutableList; -import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -165,7 +164,7 @@ public final class VideoEncoderWrapperTest { } @Override - public Codec createForAudioEncoding(Format format, List allowedMimeTypes) { + public Codec createForAudioEncoding(Format format) { throw new UnsupportedOperationException(); } From 349144f65d557203f5bfd702507d8df045383f54 Mon Sep 17 00:00:00 2001 From: samrobinson Date: Tue, 29 Nov 2022 18:08:45 +0000 Subject: [PATCH 022/183] Change TransformerInternal durationMs to durationUs. Follow-up CLs will use this duration for silent audio. PiperOrigin-RevId: 491670359 --- .../exoplayer2/transformer/ExoPlayerAssetLoader.java | 5 ++--- .../exoplayer2/transformer/TransformerInternal.java | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java index 58654427e2..7b48948a54 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java @@ -41,14 +41,13 @@ import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.text.TextOutput; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.util.Clock; -import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.VideoRendererEventListener; /* package */ final class ExoPlayerAssetLoader { public interface Listener { - void onDurationMs(long durationMs); + void onDurationUs(long durationUs); void onTrackRegistered(); @@ -174,7 +173,7 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; Timeline.Window window = new Timeline.Window(); timeline.getWindow(/* windowIndex= */ 0, window); if (!window.isPlaceholder) { - listener.onDurationMs(Util.usToMs(window.durationUs)); + listener.onDurationUs(window.durationUs); hasSentDuration = true; } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java index 358ac101e5..dd3360b6d7 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java @@ -116,7 +116,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private boolean isDrainingPipelines; private @Transformer.ProgressState int progressState; private long progressPositionMs; - private long durationMs; + private long durationUs; private @MonotonicNonNull RuntimeException cancelException; private volatile boolean released; @@ -189,7 +189,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public @Transformer.ProgressState int getProgress(ProgressHolder progressHolder) { if (progressState == PROGRESS_STATE_AVAILABLE) { - progressHolder.progress = min((int) (progressPositionMs * 100 / durationMs), 99); + progressHolder.progress = min((int) (progressPositionMs * 100 / Util.usToMs(durationUs)), 99); } return progressState; } @@ -371,17 +371,17 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; // ExoPlayerAssetLoader.Listener implementation. @Override - public void onDurationMs(long durationMs) { + public void onDurationUs(long durationUs) { applicationHandler.post( () -> { // Make progress permanently unavailable if the duration is unknown, so that it doesn't // jump to a high value at the end of the transformation if the duration is set once the // media is entirely loaded. progressState = - durationMs <= 0 || durationMs == C.TIME_UNSET + durationUs <= 0 || durationUs == C.TIME_UNSET ? PROGRESS_STATE_UNAVAILABLE : PROGRESS_STATE_AVAILABLE; - TransformerInternal.this.durationMs = durationMs; + TransformerInternal.this.durationUs = durationUs; }); } From 2f8fd87fa2b08ff01155d00d7576cb08aef3c3ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6rkem=20G=C3=BCcl=C3=BC?= Date: Mon, 5 Dec 2022 21:04:22 +0100 Subject: [PATCH 023/183] Added two new image specific properties 'tileCountHorizontal' and 'tileCountVertical' to class Format. DashManifestParser adjusted to parse these values from an EssentialProperty tag of an Image AdaptationSet. With this change, DashManifest does not have to do any parsing inside the new getThumbnailDescriptions() method. Moreover, both classes ThumbnailDescription and ThumbnailProvider adjusted to use these two properties / naming scheme accordingly. --- .../demo/DefaultThumbnailProvider.java | 10 +-- .../com/google/android/exoplayer2/Format.java | 68 +++++++++++++++++++ .../thumbnail/ThumbnailDescription.java | 18 ++--- .../source/dash/manifest/DashManifest.java | 19 +----- .../dash/manifest/DashManifestParser.java | 31 ++++++++- 5 files changed, 115 insertions(+), 31 deletions(-) diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailProvider.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailProvider.java index c06144a1b8..2006d68990 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailProvider.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DefaultThumbnailProvider.java @@ -92,7 +92,7 @@ public class DefaultThumbnailProvider implements ThumbnailProvider { if (position < thumbnailDescription.getStartTimeMs() || position > thumbnailDescription.getStartTimeMs() + thumbnailDescription.getDurationMs()) return null; - int count = thumbnailDescription.getColumns() * thumbnailDescription.getRows(); + int count = thumbnailDescription.getTileCountHorizontal() * thumbnailDescription.getTileCountVertical(); int durationPerImage = (int)(thumbnailDescription.getDurationMs() / count); @@ -101,12 +101,12 @@ public class DefaultThumbnailProvider implements ThumbnailProvider { //handle special case if position == duration if (imageNumberToUseWithinTile > count-1) imageNumberToUseWithinTile = count-1; - int intRowToUse = (int)(imageNumberToUseWithinTile / thumbnailDescription.getColumns()); + int intRowToUse = (int)(imageNumberToUseWithinTile / thumbnailDescription.getTileCountHorizontal()); - int intColToUse = imageNumberToUseWithinTile - intRowToUse * thumbnailDescription.getColumns(); + int intColToUse = imageNumberToUseWithinTile - intRowToUse * thumbnailDescription.getTileCountHorizontal(); - double thumbnailWidth = (double) thumbnailDescription.getImageWidth() / thumbnailDescription.getColumns(); - double thumbnailHeight = (double) thumbnailDescription.getImageHeight() / thumbnailDescription.getRows(); + double thumbnailWidth = (double) thumbnailDescription.getImageWidth() / thumbnailDescription.getTileCountHorizontal(); + double thumbnailHeight = (double) thumbnailDescription.getImageHeight() / thumbnailDescription.getTileCountVertical(); int cropXLeft = (int)Math.round(intColToUse * thumbnailWidth); int cropYTop = (int)Math.round(intRowToUse * thumbnailHeight); 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 ea3b552e1d..2a89d4677a 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 @@ -115,6 +115,13 @@ import java.util.UUID; *

    *
  • {@link #accessibilityChannel} *
+ * + *

Fields relevant to image formats

+ * + *
    + *
  • {@link #tileCountHorizontal} + *
  • {@link #tileCountVertical} + *
*/ public final class Format implements Bundleable { @@ -174,6 +181,11 @@ public final class Format implements Bundleable { private int accessibilityChannel; + // Image specific + + private int tileCountHorizontal; + private int tileCountVertical; + // Provided by the source. private @C.CryptoType int cryptoType; @@ -197,6 +209,9 @@ public final class Format implements Bundleable { pcmEncoding = NO_VALUE; // Text specific. accessibilityChannel = NO_VALUE; + // Image specific. + tileCountHorizontal = NO_VALUE; + tileCountVertical = NO_VALUE; // Provided by the source. cryptoType = C.CRYPTO_TYPE_NONE; } @@ -241,6 +256,9 @@ public final class Format implements Bundleable { this.encoderPadding = format.encoderPadding; // Text specific. this.accessibilityChannel = format.accessibilityChannel; + // Image specific. + this.tileCountHorizontal = format.tileCountHorizontal; + this.tileCountVertical = format.tileCountVertical; // Provided by the source. this.cryptoType = format.cryptoType; } @@ -616,6 +634,30 @@ public final class Format implements Bundleable { return this; } + // Image specific. + + /** + * Sets {@link Format#tileCountHorizontal}. The default value is {@link #NO_VALUE}. + * + * @param tileCountHorizontal The {@link Format#accessibilityChannel}. + * @return The builder. + */ + public Builder setTileCountHorizontal(int tileCountHorizontal) { + this.tileCountHorizontal = tileCountHorizontal; + return this; + } + + /** + * Sets {@link Format#tileCountVertical}. The default value is {@link #NO_VALUE}. + * + * @param tileCountVertical The {@link Format#accessibilityChannel}. + * @return The builder. + */ + public Builder setTileCountVertical(int tileCountVertical) { + this.tileCountVertical = tileCountVertical; + return this; + } + // Provided by source. /** @@ -788,6 +830,12 @@ public final class Format implements Bundleable { /** The Accessibility channel, or {@link #NO_VALUE} if not known or applicable. */ public final int accessibilityChannel; + // Image specific. + + /** Thumbnail tile count horizontal and vertical, or {@link #NO_VALUE} if not known or applicable. */ + public final int tileCountHorizontal; + public final int tileCountVertical; + // Provided by source. /** @@ -1011,6 +1059,9 @@ public final class Format implements Bundleable { encoderPadding = builder.encoderPadding == NO_VALUE ? 0 : builder.encoderPadding; // Text specific. accessibilityChannel = builder.accessibilityChannel; + // Image specific. + tileCountHorizontal = builder.tileCountHorizontal; + tileCountVertical = builder.tileCountVertical; // Provided by source. if (builder.cryptoType == C.CRYPTO_TYPE_NONE && drmInitData != null) { // Encrypted content cannot use CRYPTO_TYPE_NONE. @@ -1257,6 +1308,9 @@ public final class Format implements Bundleable { result = 31 * result + encoderPadding; // Text specific. result = 31 * result + accessibilityChannel; + // Image specific. + result = 31 * result + tileCountHorizontal; + result = 31 * result + tileCountVertical; // Provided by the source. result = 31 * result + cryptoType; hashCode = result; @@ -1293,6 +1347,8 @@ public final class Format implements Bundleable { && encoderDelay == other.encoderDelay && encoderPadding == other.encoderPadding && accessibilityChannel == other.accessibilityChannel + && tileCountHorizontal == other.tileCountHorizontal + && tileCountVertical == other.tileCountVertical && cryptoType == other.cryptoType && Float.compare(frameRate, other.frameRate) == 0 && Float.compare(pixelWidthHeightRatio, other.pixelWidthHeightRatio) == 0 @@ -1490,6 +1546,8 @@ public final class Format implements Bundleable { FIELD_ENCODER_PADDING, FIELD_ACCESSIBILITY_CHANNEL, FIELD_CRYPTO_TYPE, + FIELD_TILE_COUNT_HORIZONTAL, + FIELD_TILE_COUNT_VERTICAL, }) private @interface FieldNumber {} @@ -1523,6 +1581,8 @@ public final class Format implements Bundleable { private static final int FIELD_ENCODER_PADDING = 27; private static final int FIELD_ACCESSIBILITY_CHANNEL = 28; private static final int FIELD_CRYPTO_TYPE = 29; + private static final int FIELD_TILE_COUNT_HORIZONTAL = 30; + private static final int FIELD_TILE_COUNT_VERTICAL = 31; @Override public Bundle toBundle() { @@ -1578,6 +1638,9 @@ public final class Format implements Bundleable { bundle.putInt(keyForField(FIELD_ENCODER_PADDING), encoderPadding); // Text specific. bundle.putInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), accessibilityChannel); + // Image specific. + bundle.putInt(keyForField(FIELD_TILE_COUNT_HORIZONTAL), tileCountHorizontal); + bundle.putInt(keyForField(FIELD_TILE_COUNT_VERTICAL), tileCountVertical); // Source specific. bundle.putInt(keyForField(FIELD_CRYPTO_TYPE), cryptoType); return bundle; @@ -1652,6 +1715,11 @@ public final class Format implements Bundleable { // Text specific. .setAccessibilityChannel( bundle.getInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), DEFAULT.accessibilityChannel)) + // Image specific. + .setTileCountHorizontal( + bundle.getInt(keyForField(FIELD_TILE_COUNT_HORIZONTAL), DEFAULT.tileCountHorizontal)) + .setTileCountVertical( + bundle.getInt(keyForField(FIELD_TILE_COUNT_VERTICAL), DEFAULT.tileCountVertical)) // Source specific. .setCryptoType(bundle.getInt(keyForField(FIELD_CRYPTO_TYPE), DEFAULT.cryptoType)); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/thumbnail/ThumbnailDescription.java b/library/core/src/main/java/com/google/android/exoplayer2/thumbnail/ThumbnailDescription.java index 8984689404..cfd1f6e8fe 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/thumbnail/ThumbnailDescription.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/thumbnail/ThumbnailDescription.java @@ -7,19 +7,19 @@ public class ThumbnailDescription { private final String id; private final Uri uri; private final int bitrate; - private final int rows; - private final int columns; + private final int tileCountHorizontal; + private final int tileCountVertical; private final long startTimeMs; private final long durationMs; private final int imageWidth; // Image width (Pixel) private final int imageHeight; // Image height (Pixel) - public ThumbnailDescription(String id, Uri uri, int bitrate, int rows, int columns, long startTimeMs, long durationMs, int imageWidth, int imageHeight) { + public ThumbnailDescription(String id, Uri uri, int bitrate, int tileCountHorizontal, int tileCountVertical, long startTimeMs, long durationMs, int imageWidth, int imageHeight) { this.id = id; this.uri = uri; this.bitrate = bitrate; - this.rows = rows; - this.columns = columns; + this.tileCountHorizontal = tileCountHorizontal; + this.tileCountVertical = tileCountVertical; this.startTimeMs = startTimeMs; this.durationMs = durationMs; this.imageWidth = imageWidth; @@ -34,12 +34,12 @@ public class ThumbnailDescription { return bitrate; } - public int getRows() { - return rows; + public int getTileCountHorizontal() { + return tileCountHorizontal; } - public int getColumns() { - return columns; + public int getTileCountVertical() { + return tileCountVertical; } public long getStartTimeMs() { 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 9123ea559c..e44306a17e 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 @@ -185,22 +185,9 @@ public class DashManifest implements FilterableManifest { int bitrate = representation.format.bitrate; int imageWidth = representation.format.width; int imageHeight = representation.format.height; - // get size XxY, e.g. 10x20, where 10 is column count and 20 is row count - int rows = 1; - int cols = 1; - for (int m = 0; m < representation.essentialProperties.size(); m++) { - Descriptor descriptor = representation.essentialProperties.get(m); - if ((Ascii.equalsIgnoreCase("http://dashif.org/thumbnail_tile", descriptor.schemeIdUri) || Ascii.equalsIgnoreCase("http://dashif.org/guidelines/thumbnail_tile", descriptor.schemeIdUri)) && descriptor.value != null) { - String size = descriptor.value; - String[] sizeSplit = size.split("x"); - if (sizeSplit.length != 2) { - continue; - } - cols = Integer.parseInt(sizeSplit[0]); - rows = Integer.parseInt(sizeSplit[1]); - } - } + int tileCountHorizontal = representation.format.tileCountHorizontal; + int tileCountVertical = representation.format.tileCountVertical; long now = Util.getNowUnixTimeMs(C.TIME_UNSET); String baseUrl = castNonNull(baseUrlExclusionList.selectBaseUrl(representation.baseUrls)).url; @@ -217,7 +204,7 @@ public class DashManifest implements FilterableManifest { RangedUri rangedUri = index.getSegmentUrl(segmentNumber); DataSpec dataSpec = DashUtil.buildDataSpec(representation, baseUrl, rangedUri, /* flags= */ 0); Uri uri = dataSpec.uri; - ThumbnailDescription thumbnailDescription = new ThumbnailDescription(id, uri, bitrate, rows, cols, Util.usToMs(segmentStartTimeUs - (dynamic ? firstStartTimeUs : 0)), Util.usToMs(segmentDurationUs), imageWidth, imageHeight); + ThumbnailDescription thumbnailDescription = new ThumbnailDescription(id, uri, bitrate, tileCountHorizontal, tileCountVertical, Util.usToMs(segmentStartTimeUs - (dynamic ? firstStartTimeUs : 0)), Util.usToMs(segmentDurationUs), imageWidth, imageHeight); thumbnailDescriptions.add(thumbnailDescription); } } 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 919b1e253f..1721149cfa 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 @@ -811,6 +811,8 @@ public class DashManifestParser extends DefaultHandler roleFlags |= parseRoleFlagsFromProperties(essentialProperties); roleFlags |= parseRoleFlagsFromProperties(supplementalProperties); + Pair tileCounts = parseTileCountFromProperties(essentialProperties); + Format.Builder formatBuilder = new Format.Builder() .setId(id) @@ -820,7 +822,9 @@ public class DashManifestParser extends DefaultHandler .setPeakBitrate(bitrate) .setSelectionFlags(selectionFlags) .setRoleFlags(roleFlags) - .setLanguage(language); + .setLanguage(language) + .setTileCountHorizontal(tileCounts != null ? tileCounts.first : Format.NO_VALUE) + .setTileCountVertical(tileCounts != null ? tileCounts.second : Format.NO_VALUE); if (MimeTypes.isVideo(sampleMimeType)) { formatBuilder.setWidth(width).setHeight(height).setFrameRate(frameRate); @@ -1629,6 +1633,31 @@ public class DashManifestParser extends DefaultHandler return attributeValue.split(","); } + // Thumbnail tile information parsing + + /** + * Parses given descriptors for thumbnail tile information + * @param essentialProperties List of descriptor that contain thumbnail tile information + * @return A pair of Integer values, where the first is the count of horizontal tiles + * and the second is the count of vertical tiles, or null if no thumbnail tile information is found. + */ + @Nullable + protected Pair parseTileCountFromProperties(List essentialProperties) { + for (Descriptor descriptor : essentialProperties) { + if ((Ascii.equalsIgnoreCase("http://dashif.org/thumbnail_tile", descriptor.schemeIdUri) || Ascii.equalsIgnoreCase("http://dashif.org/guidelines/thumbnail_tile", descriptor.schemeIdUri)) && descriptor.value != null) { + String size = descriptor.value; + String[] sizeSplit = size.split("x"); + if (sizeSplit.length != 2) { + continue; + } + int tileCountHorizontal = Integer.parseInt(sizeSplit[0]); + int tileCountVertical = Integer.parseInt(sizeSplit[1]); + return Pair.create(tileCountHorizontal, tileCountVertical); + } + } + return null; + } + // Utility methods. /** From dad74276efdfc7119476a3d62746ba5a0cf3da0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6rkem=20G=C3=BCcl=C3=BC?= Date: Fri, 9 Dec 2022 15:29:23 +0100 Subject: [PATCH 024/183] Image AdaptationSets have to be excluded from duration calculation, similar to Text AdaptationSets, see issue 4029 (https://github.com/google/ExoPlayer/issues/4029). --- .../android/exoplayer2/source/dash/DashMediaSource.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 853f76b4a4..98991b37e7 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 @@ -1056,9 +1056,9 @@ public final class DashMediaSource extends BaseMediaSource { for (int i = 0; i < period.adaptationSets.size(); i++) { AdaptationSet adaptationSet = period.adaptationSets.get(i); List representations = adaptationSet.representations; - // Exclude text adaptation sets from duration calculations, if we have at least one audio + // Exclude text and image adaptation sets from duration calculations, if we have at least one audio // or video adaptation set. See: https://github.com/google/ExoPlayer/issues/4029 - if ((haveAudioVideoAdaptationSets && adaptationSet.type == C.TRACK_TYPE_TEXT) + if ((haveAudioVideoAdaptationSets && (adaptationSet.type == C.TRACK_TYPE_TEXT || adaptationSet.type == C.TRACK_TYPE_IMAGE)) || representations.isEmpty()) { continue; } @@ -1088,9 +1088,9 @@ public final class DashMediaSource extends BaseMediaSource { for (int i = 0; i < period.adaptationSets.size(); i++) { AdaptationSet adaptationSet = period.adaptationSets.get(i); List representations = adaptationSet.representations; - // Exclude text adaptation sets from duration calculations, if we have at least one audio + // Exclude text and image adaptation sets from duration calculations, if we have at least one audio // or video adaptation set. See: https://github.com/google/ExoPlayer/issues/4029 - if ((haveAudioVideoAdaptationSets && adaptationSet.type == C.TRACK_TYPE_TEXT) + if ((haveAudioVideoAdaptationSets && (adaptationSet.type == C.TRACK_TYPE_TEXT || adaptationSet.type == C.TRACK_TYPE_IMAGE)) || representations.isEmpty()) { continue; } From 4496cf551fc13be19b3aa2d6350db26489b686ce Mon Sep 17 00:00:00 2001 From: huangdarwin Date: Tue, 29 Nov 2022 18:56:00 +0000 Subject: [PATCH 025/183] HDR: Limit Z Fold 4 c2.qti decoder pending frame count. Bypass Z Fold 4 HDR10 tone-mapping bug by limiting the max frame count to 12. This passed with a value of 14, and failed with a value of 15, but I figured I'd use 12 just to be safe. PiperOrigin-RevId: 491684058 --- .../exoplayer2/transformer/DefaultCodec.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java index 6aaab0ae39..470aaf7bf3 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java @@ -20,6 +20,7 @@ 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.Assertions.checkState; import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; +import static com.google.android.exoplayer2.util.Util.MODEL; import static com.google.android.exoplayer2.util.Util.SDK_INT; import android.content.Context; @@ -64,6 +65,7 @@ public final class DefaultCodec implements Codec { private final MediaCodec mediaCodec; @Nullable private final Surface inputSurface; private final boolean decoderNeedsFrameDroppingWorkaround; + private final boolean requestedHdrToneMapping; private @MonotonicNonNull Format outputFormat; @Nullable private ByteBuffer outputBuffer; @@ -104,7 +106,7 @@ public final class DefaultCodec implements Codec { @Nullable MediaCodec mediaCodec = null; @Nullable Surface inputSurface = null; try { - boolean requestedHdrToneMapping = + requestedHdrToneMapping = SDK_INT >= 29 && Api29.isSdrToneMappingEnabled(configurationMediaFormat); mediaCodec = MediaCodec.createByCodecName(mediaCodecName); configureCodec(mediaCodec, configurationMediaFormat, isDecoder, outputSurface); @@ -162,6 +164,15 @@ public final class DefaultCodec implements Codec { // OMX video codecs should no longer exist from android.os.Build.DEVICE_INITIAL_SDK_INT 31+. return 5; } + if (requestedHdrToneMapping + && getName().equals("c2.qti.hevc.decoder") + && MODEL.equals("SM-F936B")) { + // This decoder gets stuck if too many frames are rendered without being processed when + // tone-mapping HDR10. This value is experimentally determined. See also b/260408846. + // TODO(b/260713009): Add API version check after bug is fixed on new API versions. + return 12; + } + // Otherwise don't limit the number of frames that can be pending at a time, to maximize // throughput. return UNLIMITED_PENDING_FRAME_COUNT; From 3964176421859018ebcc12c50062fb0950e5c8f1 Mon Sep 17 00:00:00 2001 From: tofunmi Date: Tue, 29 Nov 2022 19:41:18 +0000 Subject: [PATCH 026/183] Add the processor, GLEffect, texture and bitmap overlays Implements milestone 1.1 of the [overlays implementation plan](https://docs.google.com/document/d/1EcP2GN8k8N74hHZyD0KTqm9oQo5-W1dZMqIVyqVGtlo/edit#bookmark=id.76uzcie1dg9d) PiperOrigin-RevId: 491696361 --- .../exoplayer2/effect/BitmapTestUtil.java | 18 +- .../OverlayTextureProcessorPixelTest.java | 175 ++++++++++++++++++ .../shaders/fragment_shader_overlay_es2.glsl | 52 ++++++ .../shaders/vertex_shader_overlay_es2.glsl | 37 ++++ .../exoplayer2/effect/BitmapLoader.java | 56 ++++++ .../exoplayer2/effect/BitmapOverlay.java | 153 +++++++++++++++ .../android/exoplayer2/effect/BitmapUtil.java | 38 ++++ .../exoplayer2/effect/OverlayEffect.java | 44 +++++ .../exoplayer2/effect/OverlaySettings.java | 69 +++++++ .../effect/OverlayTextureProcessor.java | 147 +++++++++++++++ .../exoplayer2/effect/SimpleBitmapLoader.java | 119 ++++++++++++ .../exoplayer2/effect/TextureOverlay.java | 51 +++++ .../media/bitmap/overlay/100winners.png | Bin 0 -> 47717 bytes .../overlay_bitmap_default.png | Bin 0 -> 543803 bytes .../overlay_bitmap_scaled.png | Bin 0 -> 552677 bytes 15 files changed, 943 insertions(+), 16 deletions(-) create mode 100644 library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/OverlayTextureProcessorPixelTest.java create mode 100644 library/effect/src/main/assets/shaders/fragment_shader_overlay_es2.glsl create mode 100644 library/effect/src/main/assets/shaders/vertex_shader_overlay_es2.glsl create mode 100644 library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapLoader.java create mode 100644 library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapOverlay.java create mode 100644 library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapUtil.java create mode 100644 library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayEffect.java create mode 100644 library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlaySettings.java create mode 100644 library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayTextureProcessor.java create mode 100644 library/effect/src/main/java/com/google/android/exoplayer2/effect/SimpleBitmapLoader.java create mode 100644 library/effect/src/main/java/com/google/android/exoplayer2/effect/TextureOverlay.java create mode 100644 testdata/src/test/assets/media/bitmap/overlay/100winners.png create mode 100644 testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_default.png create mode 100644 testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_scaled.png diff --git a/library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/BitmapTestUtil.java b/library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/BitmapTestUtil.java index d8fed8623e..427fa0727f 100644 --- a/library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/BitmapTestUtil.java +++ b/library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/BitmapTestUtil.java @@ -24,7 +24,6 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; -import android.graphics.Matrix; import android.graphics.PixelFormat; import android.media.Image; import android.opengl.GLES20; @@ -211,7 +210,7 @@ public class BitmapTestUtil { // https://developer.android.com/reference/android/graphics/Bitmap.Config#ARGB_8888. bitmap.copyPixelsFromBuffer(rgba8888Buffer); // Flip the bitmap as its positive y-axis points down while OpenGL's positive y-axis points up. - return flipBitmapVertically(bitmap); + return BitmapUtil.flipBitmapVertically(bitmap); } /** @@ -227,23 +226,10 @@ public class BitmapTestUtil { bitmap.getWidth(), bitmap.getHeight(), /* useHighPrecisionColorComponents= */ false); // Put the flipped bitmap in the OpenGL texture as the bitmap's positive y-axis points down // while OpenGL's positive y-axis points up. - GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, flipBitmapVertically(bitmap), 0); + GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, BitmapUtil.flipBitmapVertically(bitmap), 0); GlUtil.checkGlError(); return texId; } - private static Bitmap flipBitmapVertically(Bitmap bitmap) { - Matrix flip = new Matrix(); - flip.postScale(1f, -1f); - return Bitmap.createBitmap( - bitmap, - /* x= */ 0, - /* y= */ 0, - bitmap.getWidth(), - bitmap.getHeight(), - flip, - /* filter= */ true); - } - private BitmapTestUtil() {} } diff --git a/library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/OverlayTextureProcessorPixelTest.java b/library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/OverlayTextureProcessorPixelTest.java new file mode 100644 index 0000000000..c770dbc9f3 --- /dev/null +++ b/library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/OverlayTextureProcessorPixelTest.java @@ -0,0 +1,175 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.effect; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; +import static com.google.android.exoplayer2.effect.BitmapTestUtil.MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE; +import static com.google.android.exoplayer2.effect.BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer; +import static com.google.android.exoplayer2.effect.BitmapTestUtil.createGlTextureFromBitmap; +import static com.google.android.exoplayer2.effect.BitmapTestUtil.getBitmapAveragePixelAbsoluteDifferenceArgb8888; +import static com.google.android.exoplayer2.effect.BitmapTestUtil.maybeSaveTestBitmapToCacheDirectory; +import static com.google.android.exoplayer2.effect.BitmapTestUtil.readBitmap; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.graphics.Bitmap; +import android.opengl.EGLContext; +import android.opengl.EGLDisplay; +import android.opengl.EGLSurface; +import android.opengl.Matrix; +import android.util.Pair; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.util.FrameProcessingException; +import com.google.android.exoplayer2.util.GlUtil; +import com.google.common.collect.ImmutableList; +import java.io.IOException; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Pixel test for texture processing via {@link OverlayTextureProcessor}. + * + *

Expected bitmaps are taken from an emulator, so tests on different emulators or physical + * devices may fail. To test on other devices, please increase the {@link + * BitmapTestUtil#MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE} and/or inspect the saved output bitmaps + * as recommended in {@link GlEffectsFrameProcessorPixelTest}. + */ +@RunWith(AndroidJUnit4.class) +public class OverlayTextureProcessorPixelTest { + public static final String OVERLAY_PNG_ASSET_PATH = "media/bitmap/overlay/100winners.png"; + public static final String ORIGINAL_PNG_ASSET_PATH = + "media/bitmap/sample_mp4_first_frame/electrical_colors/original.png"; + public static final String OVERLAY_BITMAP_DEFAULT = + "media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_default.png"; + public static final String OVERLAY_BITMAP_SCALED = + "media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_scaled.png"; + + private final Context context = getApplicationContext(); + + private @MonotonicNonNull EGLDisplay eglDisplay; + private @MonotonicNonNull EGLContext eglContext; + private @MonotonicNonNull SingleFrameGlTextureProcessor overlayTextureProcessor; + private @MonotonicNonNull EGLSurface placeholderEglSurface; + private int inputTexId; + private int inputWidth; + private int inputHeight; + + @Before + public void createGlObjects() throws IOException, GlUtil.GlException { + eglDisplay = GlUtil.createEglDisplay(); + eglContext = GlUtil.createEglContext(eglDisplay); + placeholderEglSurface = GlUtil.focusPlaceholderEglSurface(eglContext, eglDisplay); + + Bitmap inputBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH); + inputWidth = inputBitmap.getWidth(); + inputHeight = inputBitmap.getHeight(); + inputTexId = createGlTextureFromBitmap(inputBitmap); + } + + @After + public void release() throws GlUtil.GlException, FrameProcessingException { + if (overlayTextureProcessor != null) { + overlayTextureProcessor.release(); + } + GlUtil.destroyEglContext(eglDisplay, eglContext); + } + + @Test + public void drawFrame_noOverlay_leavesFrameUnchanged() throws Exception { + String testId = "drawFrame_noOverlays"; + overlayTextureProcessor = + new OverlayEffect(/* textureOverlays= */ ImmutableList.of()) + .toGlTextureProcessor(context, /* useHdr= */ false); + Pair outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight); + setupOutputTexture(outputSize.first, outputSize.second); + Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH); + + overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0); + Bitmap actualBitmap = + createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.first, outputSize.second); + + maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); + float averagePixelAbsoluteDifference = + getBitmapAveragePixelAbsoluteDifferenceArgb8888(expectedBitmap, actualBitmap, testId); + assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE); + } + + @Test + public void drawFrame_bitmapOverlay_blendsBitmapIntoFrame() throws Exception { + String testId = "drawFrame_bitmapOverlay"; + Bitmap overlayBitmap = readBitmap(OVERLAY_PNG_ASSET_PATH); + BitmapOverlay scaledBitmapOverlay = BitmapOverlay.createStaticBitmapOverlay(overlayBitmap); + overlayTextureProcessor = + new OverlayEffect(ImmutableList.of(scaledBitmapOverlay)) + .toGlTextureProcessor(context, /* useHdr= */ false); + Pair outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight); + setupOutputTexture(outputSize.first, outputSize.second); + Bitmap expectedBitmap = readBitmap(OVERLAY_BITMAP_DEFAULT); + + overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0); + Bitmap actualBitmap = + createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.first, outputSize.second); + + maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); + float averagePixelAbsoluteDifference = + getBitmapAveragePixelAbsoluteDifferenceArgb8888(expectedBitmap, actualBitmap, testId); + assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE); + } + + @Test + public void drawFrame_scaledBitmapOverlay_blendsBitmapIntoFrame() throws Exception { + String testId = "drawFrame_scaledBitmapOverlay"; + Bitmap overlayBitmap = readBitmap(OVERLAY_PNG_ASSET_PATH); + float[] scaleMatrix = GlUtil.create4x4IdentityMatrix(); + Matrix.scaleM(scaleMatrix, /* mOffset= */ 0, /* x= */ 3, /* y= */ 3, /* z= */ 1); + OverlaySettings overlaySettings = new OverlaySettings.Builder().setMatrix(scaleMatrix).build(); + BitmapOverlay staticBitmapOverlay = + BitmapOverlay.createStaticBitmapOverlay(overlayBitmap, overlaySettings); + overlayTextureProcessor = + new OverlayEffect(ImmutableList.of(staticBitmapOverlay)) + .toGlTextureProcessor(context, /* useHdr= */ false); + Pair outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight); + setupOutputTexture(outputSize.first, outputSize.second); + Bitmap expectedBitmap = readBitmap(OVERLAY_BITMAP_SCALED); + + overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0); + Bitmap actualBitmap = + createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.first, outputSize.second); + + maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap); + float averagePixelAbsoluteDifference = + getBitmapAveragePixelAbsoluteDifferenceArgb8888(expectedBitmap, actualBitmap, testId); + assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE); + } + + private void setupOutputTexture(int outputWidth, int outputHeight) throws GlUtil.GlException { + int outputTexId = + GlUtil.createTexture( + outputWidth, outputHeight, /* useHighPrecisionColorComponents= */ false); + int frameBuffer = GlUtil.createFboForTexture(outputTexId); + GlUtil.focusFramebuffer( + checkNotNull(eglDisplay), + checkNotNull(eglContext), + checkNotNull(placeholderEglSurface), + frameBuffer, + outputWidth, + outputHeight); + } +} diff --git a/library/effect/src/main/assets/shaders/fragment_shader_overlay_es2.glsl b/library/effect/src/main/assets/shaders/fragment_shader_overlay_es2.glsl new file mode 100644 index 0000000000..436edb4555 --- /dev/null +++ b/library/effect/src/main/assets/shaders/fragment_shader_overlay_es2.glsl @@ -0,0 +1,52 @@ +#version 100 +// Copyright 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ES 2 fragment shader that overlays a bitmap over a video frame. + +precision mediump float; +// Texture containing an input video frame. +uniform sampler2D uVideoTexSampler0; +// Texture containing the overlay bitmap. +uniform sampler2D uOverlayTexSampler1; +varying vec2 vVideoTexSamplingCoord; +varying vec2 vOverlayTexSamplingCoord1; + +// Manually implementing the CLAMP_TO_BORDER texture wrapping option +// (https://open.gl/textures) since it's not implemented until OpenGL ES 3.2. +vec4 getClampToBorderOverlayColor() { + if (vOverlayTexSamplingCoord1.x > 1.0 || vOverlayTexSamplingCoord1.x < 0.0 + || vOverlayTexSamplingCoord1.y > 1.0 || vOverlayTexSamplingCoord1.y < 0.0){ + return vec4(0.0, 0.0, 0.0, 0.0); + } else { + return vec4(texture2D(uOverlayTexSampler1, vOverlayTexSamplingCoord1)); + } +} + +float getMixAlpha(float videoAlpha, float overlayAlpha) { + if (videoAlpha == 0.0){ + return 1.0; + } else { + return clamp(overlayAlpha/videoAlpha, 0.0, 1.0); + } +} + +void main() { + vec4 videoColor = vec4(texture2D(uVideoTexSampler0, vVideoTexSamplingCoord)); + vec4 overlayColor = getClampToBorderOverlayColor(); + + // Blend the video decoder output and the overlay bitmap. + gl_FragColor = mix( + videoColor, overlayColor, getMixAlpha(videoColor.a, overlayColor.a)); +} diff --git a/library/effect/src/main/assets/shaders/vertex_shader_overlay_es2.glsl b/library/effect/src/main/assets/shaders/vertex_shader_overlay_es2.glsl new file mode 100644 index 0000000000..2aa40bfe9a --- /dev/null +++ b/library/effect/src/main/assets/shaders/vertex_shader_overlay_es2.glsl @@ -0,0 +1,37 @@ +#version 100 +// Copyright 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ES 2 vertex shader that leaves the frame coordinates unchanged +// and applies matrix transformations to the texture coordinates. + +uniform mat4 uAspectRatioMatrix; +uniform mat4 uOverlayMatrix; +attribute vec4 aFramePosition; +varying vec2 vVideoTexSamplingCoord; +varying vec2 vOverlayTexSamplingCoord1; + + +vec2 getTexSamplingCoord(vec2 ndcPosition) { + return vec2(ndcPosition.x * 0.5 + 0.5, ndcPosition.y * 0.5 + 0.5); +} + +void main() { + gl_Position = aFramePosition; + vec4 aOverlayPosition = uAspectRatioMatrix * uOverlayMatrix * aFramePosition; + vOverlayTexSamplingCoord1 = getTexSamplingCoord(aOverlayPosition.xy); + vVideoTexSamplingCoord = getTexSamplingCoord(aFramePosition.xy); +} + + diff --git a/library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapLoader.java b/library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapLoader.java new file mode 100644 index 0000000000..a3f7aad6f8 --- /dev/null +++ b/library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapLoader.java @@ -0,0 +1,56 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.google.android.exoplayer2.effect; + +import android.graphics.Bitmap; +import android.net.Uri; +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.MediaMetadata; +import com.google.common.util.concurrent.ListenableFuture; + +// TODO(b/258685047): delete this copy once session/BitmapLoader.java is moved to common +// (b/194284041, b/258658893). + +/** Loads images. */ +public interface BitmapLoader { + /** Decodes an image from compressed binary data. */ + ListenableFuture decodeBitmap(byte[] data); + + /** Loads an image from {@code uri}. */ + ListenableFuture loadBitmap(Uri uri); + + /** + * Loads an image from {@link MediaMetadata}. Returns null if {@code metadata} doesn't contain + * bitmap information. + * + *

By default, the method will try to decode an image from {@link MediaMetadata#artworkData} if + * it is present. Otherwise, the method will try to load an image from {@link + * MediaMetadata#artworkUri} if it is present. The method will return null if neither {@link + * MediaMetadata#artworkData} nor {@link MediaMetadata#artworkUri} is present. + */ + @Nullable + default ListenableFuture loadBitmapFromMetadata(MediaMetadata metadata) { + @Nullable ListenableFuture future; + if (metadata.artworkData != null) { + future = decodeBitmap(metadata.artworkData); + } else if (metadata.artworkUri != null) { + future = loadBitmap(metadata.artworkUri); + } else { + future = null; + } + return future; + } +} diff --git a/library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapOverlay.java b/library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapOverlay.java new file mode 100644 index 0000000000..b1957700cf --- /dev/null +++ b/library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapOverlay.java @@ -0,0 +1,153 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.effect; + +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; + +import android.graphics.Bitmap; +import android.net.Uri; +import android.opengl.GLES20; +import android.opengl.GLUtils; +import android.util.Pair; +import com.google.android.exoplayer2.util.FrameProcessingException; +import com.google.android.exoplayer2.util.GlUtil; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.ExecutionException; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + +/** + * Creates {@link TextureOverlay}s from {@link Bitmap}s. + * + *

Useful for overlaying images and animated images (e.g. GIFs). + */ +public abstract class BitmapOverlay extends TextureOverlay { + private int lastTextureId; + private @MonotonicNonNull Bitmap lastBitmap; + + /** + * Returns the overlay bitmap displayed at the specified timestamp. + * + * @param presentationTimeUs The presentation timestamp of the current frame, in microseconds. + * @throws FrameProcessingException If an error occurs while processing or drawing the frame. + */ + public abstract Bitmap getBitmap(long presentationTimeUs) throws FrameProcessingException; + + /** + * {@inheritDoc} + * + *

Gets the width and height of the cached bitmap. + * + * @param presentationTimeUs The presentation timestamp of the current frame, in microseconds. + */ + @Override + public Pair getTextureSize(long presentationTimeUs) { + return Pair.create(checkNotNull(lastBitmap).getWidth(), checkNotNull(lastBitmap).getHeight()); + } + + @Override + public int getTextureId(long presentationTimeUs) throws FrameProcessingException { + Bitmap bitmap = getBitmap(presentationTimeUs); + if (bitmap != lastBitmap) { + try { + lastBitmap = bitmap; + lastTextureId = + GlUtil.createTexture( + bitmap.getWidth(), + bitmap.getHeight(), + /* useHighPrecisionColorComponents= */ false); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, lastTextureId); + GLUtils.texImage2D( + GLES20.GL_TEXTURE_2D, + /* level= */ 0, + BitmapUtil.flipBitmapVertically(lastBitmap), + /* border= */ 0); + GlUtil.checkGlError(); + } catch (GlUtil.GlException e) { + throw new FrameProcessingException(e); + } + } + return lastTextureId; + } + + /** + * Creates a {@link BitmapOverlay} that shows the {@code overlayBitmap} in the same position and + * size throughout the whole video. + */ + public static BitmapOverlay createStaticBitmapOverlay(Bitmap overlayBitmap) { + return new BitmapOverlay() { + @Override + public Bitmap getBitmap(long presentationTimeUs) { + return overlayBitmap; + } + }; + } + + /** + * Creates a {@link BitmapOverlay} that shows the {@code overlayBitmap} in the same {@link + * OverlaySettings} throughout the whole video. + * + * @param overlaySettings The {@link OverlaySettings} configuring how the overlay is displayed on + * the frames. + */ + public static BitmapOverlay createStaticBitmapOverlay( + Bitmap overlayBitmap, OverlaySettings overlaySettings) { + return new BitmapOverlay() { + @Override + public Bitmap getBitmap(long presentationTimeUs) { + return overlayBitmap; + } + + @Override + public OverlaySettings getOverlaySettings(long presentationTimeUs) { + return overlaySettings; + } + }; + } + + /** + * Creates a {@link BitmapOverlay} that shows the input at {@code overlayBitmapUri} with the same + * {@link OverlaySettings} throughout the whole video. + * + * @param overlayBitmapUri The {@link Uri} pointing to the resource to be converted into a bitmap. + * @param overlaySettings The {@link OverlaySettings} configuring how the overlay is displayed on + * the frames. + */ + public static BitmapOverlay createStaticBitmapOverlay( + Uri overlayBitmapUri, OverlaySettings overlaySettings) { + return new BitmapOverlay() { + private @MonotonicNonNull Bitmap lastBitmap; + + @Override + public Bitmap getBitmap(long presentationTimeUs) throws FrameProcessingException { + if (lastBitmap == null) { + BitmapLoader bitmapLoader = new SimpleBitmapLoader(); + ListenableFuture future = bitmapLoader.loadBitmap(overlayBitmapUri); + try { + lastBitmap = future.get(); + } catch (ExecutionException | InterruptedException e) { + throw new FrameProcessingException(e); + } + } + return lastBitmap; + } + + @Override + public OverlaySettings getOverlaySettings(long presentationTimeUs) { + return overlaySettings; + } + }; + } +} diff --git a/library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapUtil.java b/library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapUtil.java new file mode 100644 index 0000000000..57d6c35aab --- /dev/null +++ b/library/effect/src/main/java/com/google/android/exoplayer2/effect/BitmapUtil.java @@ -0,0 +1,38 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.effect; + +import android.graphics.Bitmap; +import android.graphics.Matrix; + +/** Utility functions for working with {@link Bitmap}. */ +/* package */ final class BitmapUtil { + static Bitmap flipBitmapVertically(Bitmap bitmap) { + Matrix flip = new Matrix(); + flip.postScale(1f, -1f); + return Bitmap.createBitmap( + bitmap, + /* x= */ 0, + /* y= */ 0, + bitmap.getWidth(), + bitmap.getHeight(), + flip, + /* filter= */ true); + } + + /** Class only contains static methods. */ + private BitmapUtil() {} +} diff --git a/library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayEffect.java b/library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayEffect.java new file mode 100644 index 0000000000..93b8b886fe --- /dev/null +++ b/library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayEffect.java @@ -0,0 +1,44 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.effect; + +import android.content.Context; +import com.google.android.exoplayer2.util.FrameProcessingException; +import com.google.common.collect.ImmutableList; + +/** + * Applies a list of {@link TextureOverlay}s to a frame in FIFO order (the last overlay in the list + * is displayed on top). + */ +public final class OverlayEffect implements GlEffect { + + private final ImmutableList overlays; + + /** + * Creates a new instance for the given list of {@link TextureOverlay}s. + * + * @param textureOverlays The {@link TextureOverlay}s to be blended into the frame. + */ + public OverlayEffect(ImmutableList textureOverlays) { + this.overlays = textureOverlays; + } + + @Override + public SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr) + throws FrameProcessingException { + return new OverlayTextureProcessor(context, useHdr, overlays); + } +} diff --git a/library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlaySettings.java b/library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlaySettings.java new file mode 100644 index 0000000000..bbc0bef93e --- /dev/null +++ b/library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlaySettings.java @@ -0,0 +1,69 @@ +package com.google.android.exoplayer2.effect; +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import com.google.android.exoplayer2.util.GlUtil; +import com.google.errorprone.annotations.CanIgnoreReturnValue; + +/** Contains information to control how an {@link TextureOverlay} is displayed on the screen. */ +public final class OverlaySettings { + public final boolean useHdr; + public final float[] matrix; + + private OverlaySettings(boolean useHdr, float[] matrix) { + this.useHdr = useHdr; + this.matrix = matrix; + } + + /** A builder for {@link OverlaySettings} instances. */ + public static final class Builder { + private boolean useHdr; + private float[] matrix; + + /** Creates a new {@link Builder}. */ + public Builder() { + matrix = GlUtil.create4x4IdentityMatrix(); + } + + /** + * Sets whether input overlay comes from an HDR source. If {@code true}, colors will be in + * linear RGB BT.2020. If {@code false}, colors will be in linear RGB BT.709. + * + *

Set to {@code false} by default. + */ + @CanIgnoreReturnValue + public Builder setUsesHdr(boolean useHdr) { + this.useHdr = useHdr; + return this; + } + + /** + * Sets the {@link android.opengl.Matrix} used to transform the overlay before applying it to a + * frame. + * + *

Set to always return the identity matrix by default. + */ + @CanIgnoreReturnValue + public Builder setMatrix(float[] matrix) { + this.matrix = matrix; + return this; + } + + /** Creates an instance of {@link OverlaySettings}, using defaults if values are unset. */ + public OverlaySettings build() { + return new OverlaySettings(useHdr, matrix); + } + } +} diff --git a/library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayTextureProcessor.java b/library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayTextureProcessor.java new file mode 100644 index 0000000000..eaa38d4b6a --- /dev/null +++ b/library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayTextureProcessor.java @@ -0,0 +1,147 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.effect; + +import static com.google.android.exoplayer2.util.Assertions.checkArgument; + +import android.content.Context; +import android.opengl.GLES20; +import android.opengl.Matrix; +import android.util.Pair; +import com.google.android.exoplayer2.util.FrameProcessingException; +import com.google.android.exoplayer2.util.GlProgram; +import com.google.android.exoplayer2.util.GlUtil; +import com.google.common.collect.ImmutableList; +import java.io.IOException; + +/** Applies one or more {@link TextureOverlay}s onto each frame. */ +/* package */ final class OverlayTextureProcessor extends SingleFrameGlTextureProcessor { + + private static final String VERTEX_SHADER_PATH = "shaders/vertex_shader_overlay_es2.glsl"; + private static final String FRAGMENT_SHADER_PATH = "shaders/fragment_shader_overlay_es2.glsl"; + private static final int MATRIX_OFFSET = 0; + private static final int TRANSPARENT_TEXTURE_WIDTH_HEIGHT = 1; + + private final GlProgram glProgram; + private final ImmutableList overlays; + private final float[] aspectRatioMatrix; + private final float[] overlayMatrix; + + private int videoWidth; + private int videoHeight; + + /** + * Creates a new instance. + * + * @param context The {@link Context}. + * @param useHdr Whether input textures come from an HDR source. If {@code true}, colors will be + * in linear RGB BT.2020. If {@code false}, colors will be in linear RGB BT.709. + * @throws FrameProcessingException If a problem occurs while reading shader files. + */ + public OverlayTextureProcessor( + Context context, boolean useHdr, ImmutableList overlays) + throws FrameProcessingException { + super(useHdr); + checkArgument(!useHdr, "OverlayTextureProcessor does not support HDR colors yet."); + checkArgument( + overlays.size() <= 1, + "OverlayTextureProcessor does not support multiple overlays in the same processor yet."); + this.overlays = overlays; + aspectRatioMatrix = GlUtil.create4x4IdentityMatrix(); + overlayMatrix = GlUtil.create4x4IdentityMatrix(); + + try { + glProgram = new GlProgram(context, VERTEX_SHADER_PATH, FRAGMENT_SHADER_PATH); + } catch (GlUtil.GlException | IOException e) { + throw new FrameProcessingException(e); + } + + glProgram.setBufferAttribute( + "aFramePosition", + GlUtil.getNormalizedCoordinateBounds(), + GlUtil.HOMOGENEOUS_COORDINATE_VECTOR_SIZE); + } + + @Override + public Pair configure(int inputWidth, int inputHeight) { + videoWidth = inputWidth; + videoHeight = inputHeight; + return Pair.create(inputWidth, inputHeight); + } + + @Override + public void drawFrame(int inputTexId, long presentationTimeUs) throws FrameProcessingException { + try { + glProgram.use(); + if (!overlays.isEmpty()) { + TextureOverlay overlay = overlays.get(0); + glProgram.setSamplerTexIdUniform( + "uOverlayTexSampler1", overlay.getTextureId(presentationTimeUs), /* texUnitIndex= */ 1); + Pair overlayTextureSize = overlay.getTextureSize(presentationTimeUs); + GlUtil.setToIdentity(aspectRatioMatrix); + Matrix.scaleM( + aspectRatioMatrix, + MATRIX_OFFSET, + videoWidth / (float) overlayTextureSize.first, + videoHeight / (float) overlayTextureSize.second, + /* z= */ 1); + glProgram.setFloatsUniform("uAspectRatioMatrix", aspectRatioMatrix); + + Matrix.invertM( + overlayMatrix, + MATRIX_OFFSET, + overlay.getOverlaySettings(presentationTimeUs).matrix, + MATRIX_OFFSET); + glProgram.setFloatsUniform("uOverlayMatrix", overlayMatrix); + + } else { + glProgram.setSamplerTexIdUniform( + "uOverlayTexSampler1", createTransparentTexture(), /* texUnitIndex= */ 1); + } + glProgram.setSamplerTexIdUniform("uVideoTexSampler0", inputTexId, /* texUnitIndex= */ 0); + glProgram.bindAttributesAndUniforms(); + // The four-vertex triangle strip forms a quad. + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, /* first= */ 0, /* count= */ 4); + GlUtil.checkGlError(); + } catch (GlUtil.GlException e) { + throw new FrameProcessingException(e, presentationTimeUs); + } + } + + private int createTransparentTexture() throws FrameProcessingException { + try { + int textureId = + GlUtil.createTexture( + TRANSPARENT_TEXTURE_WIDTH_HEIGHT, + TRANSPARENT_TEXTURE_WIDTH_HEIGHT, + /* useHighPrecisionColorComponents= */ false); + GlUtil.checkGlError(); + return textureId; + } catch (GlUtil.GlException e) { + throw new FrameProcessingException(e); + } + } + + @Override + public void release() throws FrameProcessingException { + super.release(); + try { + glProgram.delete(); + } catch (GlUtil.GlException e) { + throw new FrameProcessingException(e); + } + } +} diff --git a/library/effect/src/main/java/com/google/android/exoplayer2/effect/SimpleBitmapLoader.java b/library/effect/src/main/java/com/google/android/exoplayer2/effect/SimpleBitmapLoader.java new file mode 100644 index 0000000000..ccefb887fa --- /dev/null +++ b/library/effect/src/main/java/com/google/android/exoplayer2/effect/SimpleBitmapLoader.java @@ -0,0 +1,119 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.google.android.exoplayer2.effect; + +import static com.google.android.exoplayer2.util.Assertions.checkArgument; +import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import androidx.annotation.Nullable; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.io.ByteStreams; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +// TODO(b/258685047): delete this copy once substitute is created in common +// (b/194284041, b/258658893) + +/** + * A {@link SimpleBitmapLoader} that delegates all tasks to an executor and supports fetching images + * from URIs with {@code file}, {@code http} and {@code https} schemes. + * + *

Loading tasks are delegated to an {@link ExecutorService} (or {@link + * ListeningExecutorService}) defined during construction. If no executor service is defined, all + * tasks are delegated to a single-thread executor service that is shared between instances of this + * class. + * + *

For HTTP(S) transfers, this class reads a resource only when the endpoint responds with an + * {@code HTTP 200} after sending the HTTP request. + */ +public final class SimpleBitmapLoader implements BitmapLoader { + + private static final String FILE_URI_EXCEPTION_MESSAGE = "Could not read image from file"; + + private static final Supplier DEFAULT_EXECUTOR_SERVICE = + Suppliers.memoize( + () -> MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor())); + + private final ListeningExecutorService executorService; + + /** + * Creates an instance that delegates all load tasks to a single-thread executor service shared + * between instances. + */ + public SimpleBitmapLoader() { + this(checkStateNotNull(DEFAULT_EXECUTOR_SERVICE.get())); + } + + /** Creates an instance that delegates loading tasks to the {@code executorService}. */ + public SimpleBitmapLoader(ExecutorService executorService) { + this.executorService = MoreExecutors.listeningDecorator(executorService); + } + + @Override + public ListenableFuture decodeBitmap(byte[] data) { + return executorService.submit(() -> decode(data)); + } + + @Override + public ListenableFuture loadBitmap(Uri uri) { + return executorService.submit(() -> load(uri)); + } + + private static Bitmap decode(byte[] data) { + @Nullable Bitmap bitmap = BitmapFactory.decodeByteArray(data, /* offset= */ 0, data.length); + checkArgument(bitmap != null, "Could not decode image data"); + return bitmap; + } + + private static Bitmap load(Uri uri) throws IOException { + if ("file".equals(uri.getScheme())) { + @Nullable String path = uri.getPath(); + if (path == null) { + throw new IllegalArgumentException(FILE_URI_EXCEPTION_MESSAGE); + } + @Nullable Bitmap bitmap = BitmapFactory.decodeFile(path); + if (bitmap == null) { + throw new IllegalArgumentException(FILE_URI_EXCEPTION_MESSAGE); + } + return bitmap; + } + URLConnection connection = new URL(uri.toString()).openConnection(); + if (!(connection instanceof HttpURLConnection)) { + throw new UnsupportedOperationException("Unsupported scheme: " + uri.getScheme()); + } + HttpURLConnection httpConnection = (HttpURLConnection) connection; + httpConnection.connect(); + int responseCode = httpConnection.getResponseCode(); + if (responseCode != HttpURLConnection.HTTP_OK) { + throw new IOException("Invalid response status code: " + responseCode); + } + try (InputStream inputStream = httpConnection.getInputStream()) { + return decode(ByteStreams.toByteArray(inputStream)); + } + } +} diff --git a/library/effect/src/main/java/com/google/android/exoplayer2/effect/TextureOverlay.java b/library/effect/src/main/java/com/google/android/exoplayer2/effect/TextureOverlay.java new file mode 100644 index 0000000000..868b98c8af --- /dev/null +++ b/library/effect/src/main/java/com/google/android/exoplayer2/effect/TextureOverlay.java @@ -0,0 +1,51 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.effect; + +import android.util.Pair; +import com.google.android.exoplayer2.util.FrameProcessingException; + +/** Creates overlays from OpenGL textures. */ +public abstract class TextureOverlay { + /** + * Returns the overlay texture identifier displayed at the specified timestamp. + * + * @param presentationTimeUs The presentation timestamp of the current frame, in microseconds. + * @throws FrameProcessingException If an error occurs while processing or drawing the frame. + */ + public abstract int getTextureId(long presentationTimeUs) throws FrameProcessingException; + + // This method is required to find the size of a texture given a texture identifier using OpenGL + // ES 2.0. OpenGL ES 3.1 can do this with glGetTexLevelParameteriv(). + /** + * Returns the pixel width and height of the overlay texture displayed at the specified timestamp. + * + *

This method must be called after {@link #getTextureId(long)}. + * + * @param presentationTimeUs The presentation timestamp of the current frame, in microseconds. + */ + public abstract Pair getTextureSize(long presentationTimeUs); + + /** + * Returns the {@link OverlaySettings} controlling how the overlay is displayed at the specified + * timestamp. + * + * @param presentationTimeUs The presentation timestamp of the current frame, in microseconds. + */ + public OverlaySettings getOverlaySettings(long presentationTimeUs) { + return new OverlaySettings.Builder().build(); + } +} diff --git a/testdata/src/test/assets/media/bitmap/overlay/100winners.png b/testdata/src/test/assets/media/bitmap/overlay/100winners.png new file mode 100644 index 0000000000000000000000000000000000000000..d11046a9c0290608eae29898a4d7416b27eeee14 GIT binary patch literal 47717 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 Bt@Qu^ literal 0 HcmV?d00001 diff --git a/testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_default.png b/testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_default.png new file mode 100644 index 0000000000000000000000000000000000000000..b9294aaaa8faa35b0fcc3fb09f3adece08f67b27 GIT binary patch literal 543803 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̈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

(Cdhc} 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 z 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

nbY$*!3h3h$+2dk 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�#3*g z*c6@f#2}okf3XVBz?d7GNGXLR+}~8gC|xT$jbZ@7T3$S^!!R+Rg+;olufIF*z8tQjx(Dv{Woh zjy~GniSIA32Npg=7DWK$0YC&nS}B=**mWKH!ou_xb=~5{i;r=A{TfPXblv_z*X4H% zV5XFZbZqP0-t6Gr9|5oMi(mX4>t%(iQUF8%IZXOKk4FZ4W%o3HP0Id00FB=Ju*YCh&(V_)LGQ@S-rnm!yG;B8*K zli%@Y{*Dl>nORszK*c@J=hWYFifz8ZpY6|?xo{33$)62n2F88Ydd!$V2H<)4`Ft|8 z1w`a5C&N^R+;Mke+WqWjKSx=XcyqhOlP6D5RZFZ^ORN?vc<*uj?JE?zfcF9~UcA8P zpMMVL9Tr-FNWz(p9pJtVECP<+7u5n>!H}ZR2B%MY0z<12m08-7+JC)vP<*yxCy8-G&mC4$h95C~eE*5t%F1;yVyYkmlz@ zNrOI}MVAL+f!k?BRUDnjd<_tO_?cBC*m2JD1F?(Mn^vTH@K$ z;IP_YxYtiP$G+L4X&Uq$Gj7_3D+LTrvOw-a~7hgaM7| zQ`D2A{{-PZyzr?+Wq$s*ZKu?`BU35%Q%sKI&3KSKJQayZ$2%WN$697?1kgc;GQhFM zeA6@uTmW=ur_8TF1ttHc^_f9JfBWw_x=1NS`5rdc+5EBJp z0S1?uX)@TKNjCEx9F53Gj?Fm>)A#6<1hoVu>#&zCP*sZnrfcl?4_l|wybHmeIDXc3 z*lae5$??TcKEu`36{?D>Db;N|nzQ-ikM?7J+c_g>eEs9fLO-_S_Tw1+*iN;m{RN!1 z-M_E-6Zhb#wbr&RcH1r5tBN&!Vt~Op7{i#IRzo`7DfU~m*~W~|2$Z@ZP&7Hu^t0n* zB4B+2e-Q7OqB2BWVqM$$8zez*O*4AXW_{+EADVFJ+cu)X=-^U_?+4uY5TM4}wsZYI z3otwafS9}1k&%2Kc#=hK!w2_XJ8!w+^cc`#&fvO_!9jxH=tK_XIe;Zm(N&<{$0Ioh z!YdxX)=Llx7#}F=w8GP;&+z2=3sg(idaxFFvHk?xEelyX2W&crzVFegH4a_R`TdI( zF0Y<(wUB}xXVWscVEYc!^-T@ZoFY+{C5kJ9#giAPmK6gbO2Ju+ z!{LBK-NWx)aOjAY?0W~=w{VX8)puRe`{?>UT-(E%J&d&|$_mx8!l7wGe^^cbwvGnm zSbIYXl{OLYJ?gfH>3cN2g|!B~9cqmmV_jZ2PIprvQZw#FE=sQ-^ceaIh4kVdL zA%YNRvCz;(0l=Xs49do_gB$=3cpl$<%}!`h5v+0W)C5fuh1F^a*dRJ7b`T1vRvnhr z5*Mp0XsuC^WWmY+aCC<)j5Vn5Zn59*0b#J;?{U~^G))6*cd*u>uIoUFmMLm(Emy0s zy+KnqI2?|nnL-Hcb~}9X$!BQWHl+)~4_fS!&EfYtV}jiH;P> z=yWGA<_O?Gf)XSKmOx}~Fo5OIo1R$ztG3hxJeJ^(nGz z;{G}TTZE75@zF9p*14KvS|B{L$b|FZxs!~>n;V2U11KdV0kEvIG-YZ=dm!D{R6i;= zA_tMrJPjdlu~JK3O(l&{_RNzLJd<8D%rTE)Tcm+K<+JBL^Nt*WU)k};jdgr9EFc`L z7jWK!gol9xq=0lRj%%%h^CAH(T5^h)Ab}pCbgdAuZZM?dy}qr3F&1d$dok9c>*D*! z>&@lm6FhtN0+*MU_?LhF=dfna-0ftHPB|1r1Y->D?(XpAmtTV5ptZvD7tc@>1#|=4 z-rk}t%andLKF@LbocDG#FT8hfHh^P)CHD1??Z@_?xq0V-kX}aw)OC%U+gp74$y2Dn z=5)>{k$9QX5$6Gk;lyKrVs1@kUwIJK*ka zi|w8x`Bhb+?>iiJTUcu$d>i@>6otlWxdKT-p(H!dg=V%u$xIC;*&&V&qX{W1k_gUP zG);p;UBiV)cFqED&SAIPp{{FK%Zv@v2^{JJ4*RjO*Y{kiwC_4}LFd8rJ$Cy&y!TjN zKEZ0WM6p=1<03Vr%)|%-!)0I*3)81W zEROcDg$n66k_bAhaN(RoQK*rQhBd)K^EQaNav4bz?pLca2z62bfJ``#MxhIQ^yv#+ zT~)Zc;A=?BEZe5m99``jc+XC^brv6e^bz*^J?hmGhr=F4p|RWT(f2M;rU&Q8+Veno z+qNJ{$x)yb{hv^#!yL~+4HAM=XM}+F#LjDooZq*ON5%T_VUmPhza|~dk^v+ zd2&?F++cPA;0TGilN(^uJxc)DJ53`%DYAWXO78I*9U|%{SS^V`bfQAaIlEveLCfIA zz#Q?Jz61fD(*otBenrxvd)C!aGL(4^X?u5fclh+v&+x}T zeu=*C9(27^ZCEo5Zf@S7YnTyNmKv9rmw;HJ4mwuAG5>gaKc^z8Ni6vXVypkq+PO7w zIPiPu%#ZB{+fMmMc{RH4`yKP%CmoKuZa6hthc!9_I%Cy1?(m8I>0bLI-LdYi#@V|t~HlCjf@2P z_$8LhC03VLC?wDW*f(5_qwj%l{`3Zi`hfjz59b{u)#$nohutllb5MefJS`onWrfv( z84y|$JJc_q0{{xefJC+6=$mycOc@#YQY(NQY}24`+qB+BV8VL=r8NXCAxNNWT6BE} zXEeMop~@;P>M^niSE@waG^kq(l9JP4ltSCzF{2@y9}Yb{`ry=Bc;BO3E% zwmq=Z=sKWlEv)tEdyA%SVLAhXM4^|!Qb9|FvaC?(1(wSLisA;l-5z&$yHVAUyu{dO zo~AXHLUcYbW2A-<9pXZoK%~qe^@)u{DYeB5Kv)aw23Izg*9$!bNA$|han3xEE32SViZ3cW4N@i7oV)RK7tMLn&Wja36y4kk02F~&9MG@A>dQF&9FZ5WPovFr*H~TNFTv4 zf)fHJ2-`Z#&&Z1*O@+r-LXv}kgUXn(KFmXxG%K>yk8GW1BXkUQ+-IY4Sz~73jGt5P zz`B!;n2hg1nDen}%d}6dEkh6!J1_$0@wfyA-DAKC!J@^A2$meYB(CP=9UKt^xLS(< zLB{tYt_#k?^_Insl!KBAniNP2^r1qFoiWz)p0L)`Jh;IcX#^4>oht*+gb2c|*|>B; z+v(-Y7kKjI3a?(h8m>8sTn^7;t`WZ@QJm3vbe%!He}k&}3X8=8pML6~3y-Q=C7?XN z*SP?UL?}HRAF)TMQWKH;VZMwV_wXK_(Wp3Ah2q@b-Tc)4i)nfJ1+izz^IW z>)*YP0uOm={zF-%Z{ISFqriIfjv39nyBc?QJ6v8qfs_Jm+hd`1`p(#&iQgT+?^Dgl z_`NwmJO4fRU8k&$9Oy{<_|bjw=ieKH;~^l&`(`2JhUSNCk3p0ktAp^E_E5IRUqkzI z+{>1xq#LhT9;5tL0nzIJCEI- z9sTcKF>tWiuvSDipDY*>ci5rpye8T+eF^*33Dgr>{*( z0Ql5(NfLygg45^sjQiTa%sBo12z1?7!q_^;&byC#4dP_l%iQ;;DHhYzi*qf1ZzM?w zVKV?>oGv6O2w_VP1v+9!nBG8W3n>vQvkcX%=0J|QHfC;|{yX=V(i$CG(=@26C7Pze z)zui_c$=2WHPWyyu_nhKa5x(Be$F|09yJfbp=QWNs-;M*hIkVNf zp`x8f1Ua&E`(x%K1GLAQ9PiqcOosF+mD~svOpG{+3hz|oKub`ouNPs;}av4@$>L+ ztPg*NNptG+kz(yhBmVT?^QSU*t&=Gz={~aYn>ln;;!PZXKBdgw*Ju)r&Hv?-PNNVr zzfYWr;qe`d;|d7mx#8*Wei-+oTaNorI5rV|j&3bhDVXG5ADu2ly8XDn@pDmXrpkiz zsvE;4KZ~M5wOnFVaQZ{BxP(?3YQ2W{KnGyo0o?)EZh^L8Cv9_Uu-SBI4lR@nl|_gk zeF1Aa^asN%5EW72hI8t%gmnsqYEUdZd{<+?v#9q6J}znriCwq>HWqcsAVyWK;k`o< zfP+F8EYCp_W%&$LF{R&_U}Vb$1bHaQ&SM$Ckj-YpRa?UEu|<81ryo6IAi(x$ng-r- z+RB^FYna}o$XMI8?5|W3r79tnh7+9XV!}hyGE`p)DL6_j;9UT$lTw6Tz2`a70~Qt*LDvC<#c~BftPNxP79a^PSid9x z4W~0K^{{7z_ZDi>VH2KaQFj@#ri%?LA}wRFiFjkYWUm z7zxkcp-?5sNrbes@qJ0*gOfMu9wN{cEB1tyT6hpl+V^~@f+1Lp1j5@9b7N}PjEqS^ zh}Eu+h9~|mdC>Xs3~UabA0FNsPVc`24z{|^70Z|YrJ{=I=i$0h{0d3kTV7U zP6L%k)i^yx{XuKi{&Qsvp2zW?X50H?kTaTMfjk@)CdU1iiH}E|N zN8kh`6tDC?WAXu`U_cB2(fHzFpB~t{ylxD>Zc2p%l5H`ZU$BsTV3q-=nOup%5s{Zu z?QJ5}r`m{CKV7dMiHHr6fcfvAnjC3^KIuSC&vhEO@DBtzX3zZ|z^cc98}A!&eB1L) zsj!c2??MGT2l|}+{Y<2E_WP5FWojpGdxU&Wl=VMEGcjZpT8xmdmrt;$7I^;hB{LY5 zhIPQM2kP44^|ocbi$j6kZil|(i0zx#JFY^~b|5M7*$cP#d zY|iE5>rf$6&{HyMr-3y3QoJI0afbFlZGP zMZuqkd+ge{N!lRnL?A6wUnumIg*Mr_*NW3il$4;3$HfH)F_zaQ!6is3Y;e}QbRO?m zJ7ZZb@$BUbTwWIV#b-c^P~s8{ZhZS~jq9&l?Dl(z5UG#%<-nVI+cYrN;`;hqlx2xU z!CQ?~9!hdQ%d&*4ES^4fC`yI>ZilvQvE6Q2JB7y2-+7Nhmq@~e_F*MZV~gUTxgcVk z15-=+DAFA6QD9i_Pp5tisT9+dCb4^tv;cerF429J%%|J*PQ%(b5kr< z!a%tB zY-!-RcEl7P?WI#zN9Ok&v2Dk{4}puLD*^yi{-rsPgP)bhIY;Z1vG+ddCXa2A-V2{c zIi{hOQxD4x#{$PlVHTO4=FuHH#;2X&vkv|}2qj0TrpVkqM$UT%H{P~ArXQpF#y^bi zr}hx4^F!L)csx`v)K9*9)SWPY`fxrO=euXaw)cc(wM4nRKv|YpUOdNQu|Qc#5CNS7 znhvOIpzDB}9Z=T>cXuAfDr|Q<><IJ zjf7WC78;}^jAsh9g&(CkOgBNkXBtHT_!-&p`*7+#Q^fPh=li69@G`t@(ftn*=g0&J z5i=4FPH=oA8Y(d@BvSiFj-Pk1fgWy*g;Id?GF0yXVnoC_rhQtg(s_gs3~~@_WN`G| zh3j!`VnH4f?3jCRc@0w%(hlij@mxGlWl9-RY8(YrY5zj=kaKHyJ(`Ucn6*LeN<6{n!~9S-{gq>{M3y+u`3 z89*e?M#z)>diK^%azS`Z#k?JrBFQPZ{8ySzBRB*xygv`qESxga-$xr?2uKBs&O}}HF33;}S{KsrB3_mt?hr7)V^~)!?x?BRL;lF2ldD>5MEMcm5m|rrt zqb8pprK~)VKybXy1e@i)FMWu1OyfV@9#^{WL@u-sb?EK8-``xMW}qtHAAOiJ%=q7P zx+LcesK)^s$Df@!|G9|DNhZRv5Y0o*e{}q4%#Rrm=Y&1)JNMfHKKE5Nnf`uCXf%F$ z^fY3Q`Skb`T^&dJ9zVyI)e`HA3tT;Ufkm}|UQ`f*9ooa8#;)O#o!gqVA?|99g4K-- zBA-hk!O8#tAOJ~3K~#gg(B2-4W)I+g&s;H9!DvM=&=c!7fMFKHb!*4 zk3y7DgwQ3%L2TAB`@?w;AJRkmz%cMZOfsgPNXf_cE=HgvVhLsdoZ2Box}FJ@DWp_b zEEdq3V624{+=s=YfKn;|C|N|KI5)*YJ8d20a`nLHT_!8%wna8AM)K+4SFq=Cg@9YF{O z;rUuhv7@P#h9ir95>4eQ7vuYjYzs*QCx&;E#ZKqx!LiJ11VMl~qD5d}ApJ8QX@AUu znX(LoAjI;mCj%%5&R+`p5QvZ{tnqv&S$lN6evXeFe

1g*#$$r1Q->S;OB(0E!Tt z7BT4~-*@;9LRtuA0hD~tjNle!C0z6S6>jvssgUHk?VW^x3Cy~2KZgoC-utAD53W zoax=dacYaT7G7~bOy9#51*&QZr8Ei}SXi;j)4Vp#BZ5WVGjBP=f`30=?^6cFj2R|`1O(t%0;1@HVHeI@fZMrJM@$a1i2g{X1oZodPyKRQq!?I38=DM{hPbaV-V0Bb)4^4 z_Ia3E~97S<4&9`G)RA9_H_5IOS(T6-*%4o)YR3Dw#{YY9mlu{T`{5*?H@Fnt4Z z8jG@oScI~dfjX=Lv!sxb2F=2D^`Sqa^$QZv#NTJZP=lh-sSID+_G~zMpO_GFoDw@E zu73idf&qmxq@1#mM}q-?ghf;Lkct@*1P>A&NRHRG#bSw~D3S|Yt|CU=QxpsF$T|{KgT!U zy&8?Xl#$_JQ%(1`X(Bj{gQ%9B{Cx~)#P7r^LOGt$`4lwJ2f~SPV{QWLy{nD8=tDkpxKxYa=ruY8MO|665I0xVl5UpFwnRp!PfG zvdTBfdp|vvlZsI;94>`OIa-o%(hZ1#r8ky)3E@a*Ns3F9OrOHc2Q(? zxBw(atu?Lm_#U%)GunS9=_aWZZFY@#fBCt_=N_jro@)7Vaet0alZfD)gY-dBB{1h= zgpwQ(OA%RPp(F#-)(d98Jy2})p)J0@PH@>=YYp!1?x2*yqFUhP%a^!$^M(~Zgct;u z?-75Uo}0%#j%C>ALhe>sYP`C>!~gd`e}iRp1?9QyGr>VAjk`M*(T>c|r&lW!MS;u9 zbrKv_n)iC8HP(v~|L_n0fdBfx|5s?GasBEVo7)Y(`|dk@_uY4>n+AQ?VSm`e^aj>h zY`0r%0<$t|{OM5sn%8ch7(P=izEO3faKF}B)&g<7cSrWf95@>p>VLINjz44jP~gT? z&*J-N=K|}LtsQ{_w@ER{@A*E_?YD8zPx%nJJrMhR*dMSz>`^Yh2qof8+Ald6 zcf4ljz;_ffAK#Zdnk%^w=@>8xDJ$eg>)%{;mbv!5RZ*F?WJG=7yo2wv{L<7w9RKad z1@*@^-%f3|A^;?LL~Pp5t)0<1td>hG77GYk1kunc8Gl{Zq3w9lF(@DD zLMjREnX#a>09j(eOCccp4oXQZ78MJ%1*cDjGI>fVNGZ`Z2Q*EC_4%orO#^t#f|`b- zq=&kP_YPNAPr~LI#JLiKgU6%mI#6)D_xt_5b3XzdQ+hoK!D4`5amo9td$ChG-lUn; zlSQjnL4geVH0j*(-<Rh=9F7{Hgom^mIdVC?9QfQ~rj!_qfpw>)Mn)4io|PGAKwIv75D&{!m$ zl}DIYE(3bJ_Z(Ie?ig5(5fzrm>{TPU)QYGd+nI3_R5aCI_WRe*Am{ zz{O*I06ns_8>u8LJo>(8_FOUEAW@Z@n;UF48?<#3G_rVq z-fTALdxNH_(RDrAwjaHJF�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%0Ajqs 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 IM6N<$g59;RYybcN literal 0 HcmV?d00001 diff --git a/testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_scaled.png b/testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_scaled.png new file mode 100644 index 0000000000000000000000000000000000000000..6cab7f796cda2012211d1cd6eeb0cac4d1ec7e66 GIT binary patch literal 552677 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̈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

(Cdhc} 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 z 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

S5zR$BoG7{w!wPA_2V)td_IncJ^*o~1I)6qer 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 @_u~x$7?}sRk>;cYgrkSah&Ilfq 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

tz-?Y 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

4FBkq*Vjx%_~*u7M% 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 Date: Wed, 30 Nov 2022 12:48:11 +0000 Subject: [PATCH 027/183] Rename SimpleBasePlayer.PlaylistItem to MediaItemData This better matches the terminology we use elsewhere in the Player interface, where items inside the playlist are referred to as "media item" and only the entire list is called "playlist". PiperOrigin-RevId: 491882849 --- .../android/exoplayer2/SimpleBasePlayer.java | 312 +++++++++--------- .../exoplayer2/SimpleBasePlayerTest.java | 247 +++++++------- 2 files changed, 281 insertions(+), 278 deletions(-) diff --git a/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java b/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java index aa904e591c..7a6e231a30 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java @@ -125,7 +125,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { private Size surfaceSize; private boolean newlyRenderedFirstFrame; private Metadata timedMetadata; - private ImmutableList playlistItems; + private ImmutableList playlist; private Timeline timeline; private MediaMetadata playlistMetadata; private int currentMediaItemIndex; @@ -171,7 +171,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { surfaceSize = Size.UNKNOWN; newlyRenderedFirstFrame = false; timedMetadata = new Metadata(/* presentationTimeUs= */ C.TIME_UNSET); - playlistItems = ImmutableList.of(); + playlist = ImmutableList.of(); timeline = Timeline.EMPTY; playlistMetadata = MediaMetadata.EMPTY; currentMediaItemIndex = 0; @@ -217,7 +217,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { this.surfaceSize = state.surfaceSize; this.newlyRenderedFirstFrame = state.newlyRenderedFirstFrame; this.timedMetadata = state.timedMetadata; - this.playlistItems = state.playlistItems; + this.playlist = state.playlist; this.timeline = state.timeline; this.playlistMetadata = state.playlistMetadata; this.currentMediaItemIndex = state.currentMediaItemIndex; @@ -568,21 +568,21 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the playlist items. + * Sets the list of {@link MediaItemData media items} in the playlist. * - *

All playlist items must have unique {@linkplain PlaylistItem.Builder#setUid UIDs}. + *

All items must have unique {@linkplain MediaItemData.Builder#setUid UIDs}. * - * @param playlistItems The list of playlist items. + * @param playlist The list of {@link MediaItemData media items} in the playlist. * @return This builder. */ @CanIgnoreReturnValue - public Builder setPlaylist(List playlistItems) { + public Builder setPlaylist(List playlist) { HashSet uids = new HashSet<>(); - for (int i = 0; i < playlistItems.size(); i++) { - checkArgument(uids.add(playlistItems.get(i).uid)); + for (int i = 0; i < playlist.size(); i++) { + checkArgument(uids.add(playlist.get(i).uid)); } - this.playlistItems = ImmutableList.copyOf(playlistItems); - this.timeline = new PlaylistTimeline(this.playlistItems); + this.playlist = ImmutableList.copyOf(playlist); + this.timeline = new PlaylistTimeline(this.playlist); return this; } @@ -601,8 +601,8 @@ public abstract class SimpleBasePlayer extends BasePlayer { /** * Sets the current media item index. * - *

The media item index must be less than the number of {@linkplain #setPlaylist playlist - * items}, if set. + *

The media item index must be less than the number of {@linkplain #setPlaylist media + * items in the playlist}, if set. * * @param currentMediaItemIndex The current media item index. * @return This builder. @@ -615,15 +615,15 @@ public abstract class SimpleBasePlayer extends BasePlayer { /** * Sets the current period index, or {@link C#INDEX_UNSET} to assume the first period of the - * current playlist item is played. + * current media item is played. * *

The period index must be less than the total number of {@linkplain - * PlaylistItem.Builder#setPeriods periods} in the playlist, if set, and the period at the - * specified index must be part of the {@linkplain #setCurrentMediaItemIndex current playlist + * MediaItemData.Builder#setPeriods periods} in the media item, if set, and the period at the + * specified index must be part of the {@linkplain #setCurrentMediaItemIndex current media * item}. * * @param currentPeriodIndex The current period index, or {@link C#INDEX_UNSET} to assume the - * first period of the current playlist item is played. + * first period of the current media item is played. * @return This builder. */ @CanIgnoreReturnValue @@ -640,7 +640,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { * C#INDEX_UNSET}. * *

Ads indices can only be set if there is a corresponding {@link AdPlaybackState} defined - * in the current {@linkplain PlaylistItem.Builder#setPeriods period}. + * in the current {@linkplain MediaItemData.Builder#setPeriods period}. * * @param adGroupIndex The current ad group index, or {@link C#INDEX_UNSET} if no ad is * playing. @@ -866,9 +866,9 @@ public abstract class SimpleBasePlayer extends BasePlayer { public final boolean newlyRenderedFirstFrame; /** The most recent timed metadata. */ public final Metadata timedMetadata; - /** The playlist items. */ - public final ImmutableList playlistItems; - /** The {@link Timeline} derived from the {@linkplain #playlistItems playlist items}. */ + /** The media items in the playlist. */ + public final ImmutableList playlist; + /** The {@link Timeline} derived from the {@link #playlist}. */ public final Timeline timeline; /** The playlist {@link MediaMetadata}. */ public final MediaMetadata playlistMetadata; @@ -876,7 +876,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { public final int currentMediaItemIndex; /** * The current period index, or {@link C#INDEX_UNSET} to assume the first period of the current - * playlist item is played. + * media item is played. */ public final int currentPeriodIndex; /** The current ad group index, or {@link C#INDEX_UNSET} if no ad is playing. */ @@ -1002,7 +1002,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { this.surfaceSize = builder.surfaceSize; this.newlyRenderedFirstFrame = builder.newlyRenderedFirstFrame; this.timedMetadata = builder.timedMetadata; - this.playlistItems = builder.playlistItems; + this.playlist = builder.playlist; this.timeline = builder.timeline; this.playlistMetadata = builder.playlistMetadata; this.currentMediaItemIndex = builder.currentMediaItemIndex; @@ -1059,7 +1059,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { && surfaceSize.equals(state.surfaceSize) && newlyRenderedFirstFrame == state.newlyRenderedFirstFrame && timedMetadata.equals(state.timedMetadata) - && playlistItems.equals(state.playlistItems) + && playlist.equals(state.playlist) && playlistMetadata.equals(state.playlistMetadata) && currentMediaItemIndex == state.currentMediaItemIndex && currentPeriodIndex == state.currentPeriodIndex @@ -1105,7 +1105,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { result = 31 * result + surfaceSize.hashCode(); result = 31 * result + (newlyRenderedFirstFrame ? 1 : 0); result = 31 * result + timedMetadata.hashCode(); - result = 31 * result + playlistItems.hashCode(); + result = 31 * result + playlist.hashCode(); result = 31 * result + playlistMetadata.hashCode(); result = 31 * result + currentMediaItemIndex; result = 31 * result + currentPeriodIndex; @@ -1125,28 +1125,28 @@ public abstract class SimpleBasePlayer extends BasePlayer { private static final class PlaylistTimeline extends Timeline { - private final ImmutableList playlistItems; + private final ImmutableList playlist; private final int[] firstPeriodIndexByWindowIndex; private final int[] windowIndexByPeriodIndex; private final HashMap periodIndexByUid; - public PlaylistTimeline(ImmutableList playlistItems) { - int playlistItemCount = playlistItems.size(); - this.playlistItems = playlistItems; - this.firstPeriodIndexByWindowIndex = new int[playlistItemCount]; + public PlaylistTimeline(ImmutableList playlist) { + int mediaItemCount = playlist.size(); + this.playlist = playlist; + this.firstPeriodIndexByWindowIndex = new int[mediaItemCount]; int periodCount = 0; - for (int i = 0; i < playlistItemCount; i++) { - PlaylistItem playlistItem = playlistItems.get(i); + for (int i = 0; i < mediaItemCount; i++) { + MediaItemData mediaItemData = playlist.get(i); firstPeriodIndexByWindowIndex[i] = periodCount; - periodCount += getPeriodCountInPlaylistItem(playlistItem); + periodCount += getPeriodCountInMediaItem(mediaItemData); } this.windowIndexByPeriodIndex = new int[periodCount]; this.periodIndexByUid = new HashMap<>(); int periodIndex = 0; - for (int i = 0; i < playlistItemCount; i++) { - PlaylistItem playlistItem = playlistItems.get(i); - for (int j = 0; j < getPeriodCountInPlaylistItem(playlistItem); j++) { - periodIndexByUid.put(playlistItem.getPeriodUid(j), periodIndex); + for (int i = 0; i < mediaItemCount; i++) { + MediaItemData mediaItemData = playlist.get(i); + for (int j = 0; j < getPeriodCountInMediaItem(mediaItemData); j++) { + periodIndexByUid.put(mediaItemData.getPeriodUid(j), periodIndex); windowIndexByPeriodIndex[periodIndex] = i; periodIndex++; } @@ -1155,7 +1155,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public int getWindowCount() { - return playlistItems.size(); + return playlist.size(); } @Override @@ -1184,7 +1184,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { - return playlistItems + return playlist .get(windowIndex) .getWindow(firstPeriodIndexByWindowIndex[windowIndex], window); } @@ -1204,7 +1204,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { public Period getPeriod(int periodIndex, Period period, boolean setIds) { int windowIndex = windowIndexByPeriodIndex[periodIndex]; int periodIndexInWindow = periodIndex - firstPeriodIndexByWindowIndex[windowIndex]; - return playlistItems.get(windowIndex).getPeriod(windowIndex, periodIndexInWindow, period); + return playlist.get(windowIndex).getPeriod(windowIndex, periodIndexInWindow, period); } @Override @@ -1217,21 +1217,22 @@ public abstract class SimpleBasePlayer extends BasePlayer { public Object getUidOfPeriod(int periodIndex) { int windowIndex = windowIndexByPeriodIndex[periodIndex]; int periodIndexInWindow = periodIndex - firstPeriodIndexByWindowIndex[windowIndex]; - return playlistItems.get(windowIndex).getPeriodUid(periodIndexInWindow); + return playlist.get(windowIndex).getPeriodUid(periodIndexInWindow); } - private static int getPeriodCountInPlaylistItem(PlaylistItem playlistItem) { - return playlistItem.periods.isEmpty() ? 1 : playlistItem.periods.size(); + private static int getPeriodCountInMediaItem(MediaItemData mediaItemData) { + return mediaItemData.periods.isEmpty() ? 1 : mediaItemData.periods.size(); } } /** - * An immutable description of a playlist item, containing both static setup information like - * {@link MediaItem} and dynamic data that is generally read from the media like the duration. + * An immutable description of an item in the playlist, containing both static setup information + * like {@link MediaItem} and dynamic data that is generally read from the media like the + * duration. */ - protected static final class PlaylistItem { + protected static final class MediaItemData { - /** A builder for {@link PlaylistItem} objects. */ + /** A builder for {@link MediaItemData} objects. */ public static final class Builder { private Object uid; @@ -1254,7 +1255,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { /** * Creates the builder. * - * @param uid The unique identifier of the playlist item within a playlist. This value will be + * @param uid The unique identifier of the media item within a playlist. This value will be * set as {@link Timeline.Window#uid} for this item. */ public Builder(Object uid) { @@ -1276,31 +1277,31 @@ public abstract class SimpleBasePlayer extends BasePlayer { periods = ImmutableList.of(); } - private Builder(PlaylistItem playlistItem) { - this.uid = playlistItem.uid; - this.tracks = playlistItem.tracks; - this.mediaItem = playlistItem.mediaItem; - this.mediaMetadata = playlistItem.mediaMetadata; - this.manifest = playlistItem.manifest; - this.liveConfiguration = playlistItem.liveConfiguration; - this.presentationStartTimeMs = playlistItem.presentationStartTimeMs; - this.windowStartTimeMs = playlistItem.windowStartTimeMs; - this.elapsedRealtimeEpochOffsetMs = playlistItem.elapsedRealtimeEpochOffsetMs; - this.isSeekable = playlistItem.isSeekable; - this.isDynamic = playlistItem.isDynamic; - this.defaultPositionUs = playlistItem.defaultPositionUs; - this.durationUs = playlistItem.durationUs; - this.positionInFirstPeriodUs = playlistItem.positionInFirstPeriodUs; - this.isPlaceholder = playlistItem.isPlaceholder; - this.periods = playlistItem.periods; + private Builder(MediaItemData mediaItemData) { + this.uid = mediaItemData.uid; + this.tracks = mediaItemData.tracks; + this.mediaItem = mediaItemData.mediaItem; + this.mediaMetadata = mediaItemData.mediaMetadata; + this.manifest = mediaItemData.manifest; + this.liveConfiguration = mediaItemData.liveConfiguration; + this.presentationStartTimeMs = mediaItemData.presentationStartTimeMs; + this.windowStartTimeMs = mediaItemData.windowStartTimeMs; + this.elapsedRealtimeEpochOffsetMs = mediaItemData.elapsedRealtimeEpochOffsetMs; + this.isSeekable = mediaItemData.isSeekable; + this.isDynamic = mediaItemData.isDynamic; + this.defaultPositionUs = mediaItemData.defaultPositionUs; + this.durationUs = mediaItemData.durationUs; + this.positionInFirstPeriodUs = mediaItemData.positionInFirstPeriodUs; + this.isPlaceholder = mediaItemData.isPlaceholder; + this.periods = mediaItemData.periods; } /** - * Sets the unique identifier of this playlist item within a playlist. + * Sets the unique identifier of this media item within a playlist. * *

This value will be set as {@link Timeline.Window#uid} for this item. * - * @param uid The unique identifier of this playlist item within a playlist. + * @param uid The unique identifier of this media item within a playlist. * @return This builder. */ @CanIgnoreReturnValue @@ -1310,9 +1311,9 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the {@link Tracks} of this playlist item. + * Sets the {@link Tracks} of this media item. * - * @param tracks The {@link Tracks} of this playlist item. + * @param tracks The {@link Tracks} of this media item. * @return This builder. */ @CanIgnoreReturnValue @@ -1322,9 +1323,9 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the {@link MediaItem} for this playlist item. + * Sets the {@link MediaItem}. * - * @param mediaItem The {@link MediaItem} for this playlist item. + * @param mediaItem The {@link MediaItem}. * @return This builder. */ @CanIgnoreReturnValue @@ -1354,9 +1355,9 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the manifest of the playlist item. + * Sets the manifest of the media item. * - * @param manifest The manifest of the playlist item, or null if not applicable. + * @param manifest The manifest of the media item, or null if not applicable. * @return This builder. */ @CanIgnoreReturnValue @@ -1366,11 +1367,10 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the active {@link MediaItem.LiveConfiguration}, or null if the playlist item is not - * live. + * Sets the active {@link MediaItem.LiveConfiguration}, or null if the media item is not live. * * @param liveConfiguration The active {@link MediaItem.LiveConfiguration}, or null if the - * playlist item is not live. + * media item is not live. * @return This builder. */ @CanIgnoreReturnValue @@ -1431,9 +1431,9 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets whether it's possible to seek within this playlist item. + * Sets whether it's possible to seek within this media item. * - * @param isSeekable Whether it's possible to seek within this playlist item. + * @param isSeekable Whether it's possible to seek within this media item. * @return This builder. */ @CanIgnoreReturnValue @@ -1443,9 +1443,9 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets whether this playlist item may change over time, for example a moving live window. + * Sets whether this media item may change over time, for example a moving live window. * - * @param isDynamic Whether this playlist item may change over time, for example a moving live + * @param isDynamic Whether this media item may change over time, for example a moving live * window. * @return This builder. */ @@ -1456,13 +1456,13 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the default position relative to the start of the playlist item at which to begin + * Sets the default position relative to the start of the media item at which to begin * playback, in microseconds. * *

The default position must be less or equal to the {@linkplain #setDurationUs duration}, * is set. * - * @param defaultPositionUs The default position relative to the start of the playlist item at + * @param defaultPositionUs The default position relative to the start of the media item at * which to begin playback, in microseconds. * @return This builder. */ @@ -1474,14 +1474,14 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the duration of the playlist item, in microseconds. + * Sets the duration of the media item, in microseconds. * *

If both this duration and all {@linkplain #setPeriods period} durations are set, the sum * of this duration and the {@linkplain #setPositionInFirstPeriodUs offset in the first * period} must match the total duration of all periods. * - * @param durationUs The duration of the playlist item, in microseconds, or {@link - * C#TIME_UNSET} if unknown. + * @param durationUs The duration of the media item, in microseconds, or {@link C#TIME_UNSET} + * if unknown. * @return This builder. */ @CanIgnoreReturnValue @@ -1492,11 +1492,11 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the position of the start of this playlist item relative to the start of the first - * period belonging to it, in microseconds. + * Sets the position of the start of this media item relative to the start of the first period + * belonging to it, in microseconds. * - * @param positionInFirstPeriodUs The position of the start of this playlist item relative to - * the start of the first period belonging to it, in microseconds. + * @param positionInFirstPeriodUs The position of the start of this media item relative to the + * start of the first period belonging to it, in microseconds. * @return This builder. */ @CanIgnoreReturnValue @@ -1507,11 +1507,11 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets whether this playlist item contains placeholder information because the real - * information has yet to be loaded. + * Sets whether this media item contains placeholder information because the real information + * has yet to be loaded. * - * @param isPlaceholder Whether this playlist item contains placeholder information because - * the real information has yet to be loaded. + * @param isPlaceholder Whether this media item contains placeholder information because the + * real information has yet to be loaded. * @return This builder. */ @CanIgnoreReturnValue @@ -1521,15 +1521,14 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the list of {@linkplain PeriodData periods} in this playlist item. + * Sets the list of {@linkplain PeriodData periods} in this media item. * *

All periods must have unique {@linkplain PeriodData.Builder#setUid UIDs} and only the * last period is allowed to have an unset {@linkplain PeriodData.Builder#setDurationUs * duration}. * - * @param periods The list of {@linkplain PeriodData periods} in this playlist item, or an - * empty list to assume a single period without ads and the same duration as the playlist - * item. + * @param periods The list of {@linkplain PeriodData periods} in this media item, or an empty + * list to assume a single period without ads and the same duration as the media item. * @return This builder. */ @CanIgnoreReturnValue @@ -1545,17 +1544,17 @@ public abstract class SimpleBasePlayer extends BasePlayer { return this; } - /** Builds the {@link PlaylistItem}. */ - public PlaylistItem build() { - return new PlaylistItem(this); + /** Builds the {@link MediaItemData}. */ + public MediaItemData build() { + return new MediaItemData(this); } } - /** The unique identifier of this playlist item. */ + /** The unique identifier of this media item. */ public final Object uid; - /** The {@link Tracks} of this playlist item. */ + /** The {@link Tracks} of this media item. */ public final Tracks tracks; - /** The {@link MediaItem} for this playlist item. */ + /** The {@link MediaItem}. */ public final MediaItem mediaItem; /** * The {@link MediaMetadata}, including static data from the {@link MediaItem#mediaMetadata @@ -1565,9 +1564,9 @@ public abstract class SimpleBasePlayer extends BasePlayer { * {@link Format#metadata Formats}. */ @Nullable public final MediaMetadata mediaMetadata; - /** The manifest of the playlist item, or null if not applicable. */ + /** The manifest of the media item, or null if not applicable. */ @Nullable public final Object manifest; - /** The active {@link MediaItem.LiveConfiguration}, or null if the playlist item is not live. */ + /** The active {@link MediaItem.LiveConfiguration}, or null if the media item is not live. */ @Nullable public final MediaItem.LiveConfiguration liveConfiguration; /** * The start time of the live presentation, in milliseconds since the Unix epoch, or {@link @@ -1585,37 +1584,37 @@ public abstract class SimpleBasePlayer extends BasePlayer { * applicable. */ public final long elapsedRealtimeEpochOffsetMs; - /** Whether it's possible to seek within this playlist item. */ + /** Whether it's possible to seek within this media item. */ public final boolean isSeekable; - /** Whether this playlist item may change over time, for example a moving live window. */ + /** Whether this media item may change over time, for example a moving live window. */ public final boolean isDynamic; /** - * The default position relative to the start of the playlist item at which to begin playback, - * in microseconds. + * The default position relative to the start of the media item at which to begin playback, in + * microseconds. */ public final long defaultPositionUs; - /** The duration of the playlist item, in microseconds, or {@link C#TIME_UNSET} if unknown. */ + /** The duration of the media item, in microseconds, or {@link C#TIME_UNSET} if unknown. */ public final long durationUs; /** - * The position of the start of this playlist item relative to the start of the first period + * The position of the start of this media item relative to the start of the first period * belonging to it, in microseconds. */ public final long positionInFirstPeriodUs; /** - * Whether this playlist item contains placeholder information because the real information has - * yet to be loaded. + * Whether this media item contains placeholder information because the real information has yet + * to be loaded. */ public final boolean isPlaceholder; /** - * The list of {@linkplain PeriodData periods} in this playlist item, or an empty list to assume - * a single period without ads and the same duration as the playlist item. + * The list of {@linkplain PeriodData periods} in this media item, or an empty list to assume a + * single period without ads and the same duration as the media item. */ public final ImmutableList periods; private final long[] periodPositionInWindowUs; private final MediaMetadata combinedMediaMetadata; - private PlaylistItem(Builder builder) { + private MediaItemData(Builder builder) { if (builder.liveConfiguration == null) { checkArgument(builder.presentationStartTimeMs == C.TIME_UNSET); checkArgument(builder.windowStartTimeMs == C.TIME_UNSET); @@ -1665,26 +1664,26 @@ public abstract class SimpleBasePlayer extends BasePlayer { if (this == o) { return true; } - if (!(o instanceof PlaylistItem)) { + if (!(o instanceof MediaItemData)) { return false; } - PlaylistItem playlistItem = (PlaylistItem) o; - return this.uid.equals(playlistItem.uid) - && this.tracks.equals(playlistItem.tracks) - && this.mediaItem.equals(playlistItem.mediaItem) - && Util.areEqual(this.mediaMetadata, playlistItem.mediaMetadata) - && Util.areEqual(this.manifest, playlistItem.manifest) - && Util.areEqual(this.liveConfiguration, playlistItem.liveConfiguration) - && this.presentationStartTimeMs == playlistItem.presentationStartTimeMs - && this.windowStartTimeMs == playlistItem.windowStartTimeMs - && this.elapsedRealtimeEpochOffsetMs == playlistItem.elapsedRealtimeEpochOffsetMs - && this.isSeekable == playlistItem.isSeekable - && this.isDynamic == playlistItem.isDynamic - && this.defaultPositionUs == playlistItem.defaultPositionUs - && this.durationUs == playlistItem.durationUs - && this.positionInFirstPeriodUs == playlistItem.positionInFirstPeriodUs - && this.isPlaceholder == playlistItem.isPlaceholder - && this.periods.equals(playlistItem.periods); + MediaItemData mediaItemData = (MediaItemData) o; + return this.uid.equals(mediaItemData.uid) + && this.tracks.equals(mediaItemData.tracks) + && this.mediaItem.equals(mediaItemData.mediaItem) + && Util.areEqual(this.mediaMetadata, mediaItemData.mediaMetadata) + && Util.areEqual(this.manifest, mediaItemData.manifest) + && Util.areEqual(this.liveConfiguration, mediaItemData.liveConfiguration) + && this.presentationStartTimeMs == mediaItemData.presentationStartTimeMs + && this.windowStartTimeMs == mediaItemData.windowStartTimeMs + && this.elapsedRealtimeEpochOffsetMs == mediaItemData.elapsedRealtimeEpochOffsetMs + && this.isSeekable == mediaItemData.isSeekable + && this.isDynamic == mediaItemData.isDynamic + && this.defaultPositionUs == mediaItemData.defaultPositionUs + && this.durationUs == mediaItemData.durationUs + && this.positionInFirstPeriodUs == mediaItemData.positionInFirstPeriodUs + && this.isPlaceholder == mediaItemData.isPlaceholder + && this.periods.equals(mediaItemData.periods); } @Override @@ -1733,7 +1732,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { } private Timeline.Period getPeriod( - int windowIndex, int periodIndexInPlaylistItem, Timeline.Period period) { + int windowIndex, int periodIndexInMediaItem, Timeline.Period period) { if (periods.isEmpty()) { period.set( /* id= */ uid, @@ -1744,7 +1743,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { AdPlaybackState.NONE, isPlaceholder); } else { - PeriodData periodData = periods.get(periodIndexInPlaylistItem); + PeriodData periodData = periods.get(periodIndexInMediaItem); Object periodId = periodData.uid; Object periodUid = Pair.create(uid, periodId); period.set( @@ -1752,18 +1751,18 @@ public abstract class SimpleBasePlayer extends BasePlayer { periodUid, windowIndex, periodData.durationUs, - periodPositionInWindowUs[periodIndexInPlaylistItem], + periodPositionInWindowUs[periodIndexInMediaItem], periodData.adPlaybackState, periodData.isPlaceholder); } return period; } - private Object getPeriodUid(int periodIndexInPlaylistItem) { + private Object getPeriodUid(int periodIndexInMediaItem) { if (periods.isEmpty()) { return uid; } - Object periodId = periods.get(periodIndexInPlaylistItem).uid; + Object periodId = periods.get(periodIndexInMediaItem).uid; return Pair.create(uid, periodId); } @@ -1787,7 +1786,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { } } - /** Data describing the properties of a period inside a {@link PlaylistItem}. */ + /** Data describing the properties of a period inside a {@link MediaItemData}. */ protected static final class PeriodData { /** A builder for {@link PeriodData} objects. */ @@ -1801,7 +1800,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { /** * Creates the builder. * - * @param uid The unique identifier of the period within its playlist item. + * @param uid The unique identifier of the period within its media item. */ public Builder(Object uid) { this.uid = uid; @@ -1818,9 +1817,9 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Sets the unique identifier of the period within its playlist item. + * Sets the unique identifier of the period within its media item. * - * @param uid The unique identifier of the period within its playlist item. + * @param uid The unique identifier of the period within its media item. * @return This builder. */ @CanIgnoreReturnValue @@ -1832,7 +1831,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { /** * Sets the total duration of the period, in microseconds, or {@link C#TIME_UNSET} if unknown. * - *

Only the last period in a playlist item can have an unknown duration. + *

Only the last period in a media item can have an unknown duration. * * @param durationUs The total duration of the period, in microseconds, or {@link * C#TIME_UNSET} if unknown. @@ -1878,11 +1877,11 @@ public abstract class SimpleBasePlayer extends BasePlayer { } } - /** The unique identifier of the period within its playlist item. */ + /** The unique identifier of the period within its media item. */ public final Object uid; /** * The total duration of the period, in microseconds, or {@link C#TIME_UNSET} if unknown. Only - * the last period in a playlist item can have an unknown duration. + * the last period in a media item can have an unknown duration. */ public final long durationUs; /** @@ -2539,8 +2538,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { if (timelineChanged) { @Player.TimelineChangeReason - int timelineChangeReason = - getTimelineChangeReason(previousState.playlistItems, newState.playlistItems); + int timelineChangeReason = getTimelineChangeReason(previousState.playlist, newState.playlist); listeners.queueEvent( Player.EVENT_TIMELINE_CHANGED, listener -> listener.onTimelineChanged(newState.timeline, timelineChangeReason)); @@ -2567,7 +2565,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { MediaItem mediaItem = state.timeline.isEmpty() ? null - : state.playlistItems.get(state.currentMediaItemIndex).mediaItem; + : state.playlist.get(state.currentMediaItemIndex).mediaItem; listeners.queueEvent( Player.EVENT_MEDIA_ITEM_TRANSITION, listener -> listener.onMediaItemTransition(mediaItem, mediaItemTransitionReason)); @@ -2795,15 +2793,15 @@ public abstract class SimpleBasePlayer extends BasePlayer { } private static Tracks getCurrentTracksInternal(State state) { - return state.playlistItems.isEmpty() + return state.playlist.isEmpty() ? Tracks.EMPTY - : state.playlistItems.get(state.currentMediaItemIndex).tracks; + : state.playlist.get(state.currentMediaItemIndex).tracks; } private static MediaMetadata getMediaMetadataInternal(State state) { - return state.playlistItems.isEmpty() + return state.playlist.isEmpty() ? MediaMetadata.EMPTY - : state.playlistItems.get(state.currentMediaItemIndex).combinedMediaMetadata; + : state.playlist.get(state.currentMediaItemIndex).combinedMediaMetadata; } private static int getCurrentPeriodIndexInternal(State state, Timeline.Window window) { @@ -2817,7 +2815,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { } private static @Player.TimelineChangeReason int getTimelineChangeReason( - List previousPlaylist, List newPlaylist) { + List previousPlaylist, List newPlaylist) { if (previousPlaylist.size() != newPlaylist.size()) { return Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED; } @@ -2835,11 +2833,11 @@ public abstract class SimpleBasePlayer extends BasePlayer { // We were asked to report a discontinuity. return newState.positionDiscontinuityReason; } - if (previousState.playlistItems.isEmpty()) { - // First change from an empty timeline is not reported as a discontinuity. + if (previousState.playlist.isEmpty()) { + // First change from an empty playlist is not reported as a discontinuity. return C.INDEX_UNSET; } - if (newState.playlistItems.isEmpty()) { + if (newState.playlist.isEmpty()) { // The playlist became empty. return Player.DISCONTINUITY_REASON_REMOVE; } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java b/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java index 41e49bd0ab..0995639a66 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java @@ -117,15 +117,15 @@ public class SimpleBasePlayerTest { .setTimedMetadata(new Metadata()) .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build(), - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setPeriods( ImmutableList.of( new SimpleBasePlayer.PeriodData.Builder(/* uid= */ new Object()) .setAdPlaybackState( new AdPlaybackState( /* adsId= */ new Object(), - /* adGroupTimesUs= */ 555, + /* adGroupTimesUs...= */ 555, 666)) .build())) .build())) @@ -149,9 +149,9 @@ public class SimpleBasePlayerTest { } @Test - public void playlistItemBuildUpon_build_isEqual() { - SimpleBasePlayer.PlaylistItem playlistItem = - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + public void mediaItemDataBuildUpon_build_isEqual() { + SimpleBasePlayer.MediaItemData mediaItemData = + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setTracks( new Tracks( ImmutableList.of( @@ -179,10 +179,10 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.PeriodData.Builder(/* uid= */ new Object()).build())) .build(); - SimpleBasePlayer.PlaylistItem newPlaylistItem = playlistItem.buildUpon().build(); + SimpleBasePlayer.MediaItemData newMediaItemData = mediaItemData.buildUpon().build(); - assertThat(newPlaylistItem).isEqualTo(playlistItem); - assertThat(newPlaylistItem.hashCode()).isEqualTo(playlistItem.hashCode()); + assertThat(newMediaItemData).isEqualTo(mediaItemData); + assertThat(newMediaItemData.hashCode()).isEqualTo(mediaItemData.hashCode()); } @Test @@ -192,7 +192,7 @@ public class SimpleBasePlayerTest { .setIsPlaceholder(true) .setDurationUs(600_000) .setAdPlaybackState( - new AdPlaybackState(/* adsId= */ new Object(), /* adGroupTimesUs= */ 555, 666)) + new AdPlaybackState(/* adsId= */ new Object(), /* adGroupTimesUs...= */ 555, 666)) .build(); SimpleBasePlayer.PeriodData newPeriodData = periodData.buildUpon().build(); @@ -227,16 +227,16 @@ public class SimpleBasePlayerTest { Size surfaceSize = new Size(480, 360); DeviceInfo deviceInfo = new DeviceInfo(DeviceInfo.PLAYBACK_TYPE_LOCAL, /* minVolume= */ 3, /* maxVolume= */ 7); - ImmutableList playlist = + ImmutableList playlist = ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build(), - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setPeriods( ImmutableList.of( new SimpleBasePlayer.PeriodData.Builder(/* uid= */ new Object()) .setAdPlaybackState( new AdPlaybackState( - /* adsId= */ new Object(), /* adGroupTimesUs= */ 555, 666)) + /* adsId= */ new Object(), /* adGroupTimesUs...= */ 555, 666)) .build())) .build()); MediaMetadata playlistMetadata = new MediaMetadata.Builder().setArtist("artist").build(); @@ -319,7 +319,7 @@ public class SimpleBasePlayerTest { assertThat(state.surfaceSize).isEqualTo(surfaceSize); assertThat(state.newlyRenderedFirstFrame).isTrue(); assertThat(state.timedMetadata).isEqualTo(timedMetadata); - assertThat(state.playlistItems).isEqualTo(playlist); + assertThat(state.playlist).isEqualTo(playlist); assertThat(state.playlistMetadata).isEqualTo(playlistMetadata); assertThat(state.currentMediaItemIndex).isEqualTo(1); assertThat(state.currentPeriodIndex).isEqualTo(1); @@ -376,8 +376,9 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build(), - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build())) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) + .build())) .setCurrentMediaItemIndex(2) .build()); } @@ -390,8 +391,9 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build(), - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build())) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) + .build())) .setCurrentPeriodIndex(2) .build()); } @@ -404,8 +406,9 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build(), - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build())) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) + .build())) .setCurrentMediaItemIndex(0) .setCurrentPeriodIndex(1) .build()); @@ -419,14 +422,14 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setPeriods( ImmutableList.of( new SimpleBasePlayer.PeriodData.Builder(/* uid= */ new Object()) .setAdPlaybackState( new AdPlaybackState( /* adsId= */ new Object(), - /* adGroupTimesUs= */ 123)) + /* adGroupTimesUs...= */ 123)) .build())) .build())) .setCurrentAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2) @@ -441,14 +444,14 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setPeriods( ImmutableList.of( new SimpleBasePlayer.PeriodData.Builder(/* uid= */ new Object()) .setAdPlaybackState( new AdPlaybackState( /* adsId= */ new Object(), - /* adGroupTimesUs= */ 123) + /* adGroupTimesUs...= */ 123) .withAdCount( /* adGroupIndex= */ 0, /* adCount= */ 2)) .build())) @@ -473,7 +476,7 @@ public class SimpleBasePlayerTest { } @Test - public void stateBuilderBuild_multiplePlaylistItemsWithSameIds_throwsException() { + public void stateBuilderBuild_multipleMediaItemsWithSameIds_throwsException() { Object uid = new Object(); assertThrows( @@ -482,8 +485,8 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(uid).build(), - new SimpleBasePlayer.PlaylistItem.Builder(uid).build())) + new SimpleBasePlayer.MediaItemData.Builder(uid).build(), + new SimpleBasePlayer.MediaItemData.Builder(uid).build())) .build()); } @@ -524,7 +527,7 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build())) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build())) .setContentPositionMs(4000) .setPlayWhenReady(true, Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setPlaybackState(Player.STATE_READY) @@ -546,7 +549,7 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build())) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build())) .setContentPositionMs(4000) .setPlaybackState(Player.STATE_BUFFERING) .build(); @@ -566,14 +569,14 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setPeriods( ImmutableList.of( new SimpleBasePlayer.PeriodData.Builder(/* uid= */ new Object()) .setAdPlaybackState( new AdPlaybackState( /* adsId= */ new Object(), - /* adGroupTimesUs= */ 123) + /* adGroupTimesUs...= */ 123) .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2)) .build())) .build())) @@ -600,14 +603,14 @@ public class SimpleBasePlayerTest { new SimpleBasePlayer.State.Builder() .setPlaylist( ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setPeriods( ImmutableList.of( new SimpleBasePlayer.PeriodData.Builder(/* uid= */ new Object()) .setAdPlaybackState( new AdPlaybackState( /* adsId= */ new Object(), - /* adGroupTimesUs= */ 123) + /* adGroupTimesUs...= */ 123) .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2)) .build())) .build())) @@ -624,7 +627,7 @@ public class SimpleBasePlayerTest { } @Test - public void playlistItemBuilderBuild_setsCorrectValues() { + public void mediaItemDataBuilderBuild_setsCorrectValues() { Object uid = new Object(); Tracks tracks = new Tracks( @@ -642,8 +645,8 @@ public class SimpleBasePlayerTest { ImmutableList periods = ImmutableList.of(new SimpleBasePlayer.PeriodData.Builder(/* uid= */ new Object()).build()); - SimpleBasePlayer.PlaylistItem playlistItem = - new SimpleBasePlayer.PlaylistItem.Builder(uid) + SimpleBasePlayer.MediaItemData mediaItemData = + new SimpleBasePlayer.MediaItemData.Builder(uid) .setTracks(tracks) .setMediaItem(mediaItem) .setMediaMetadata(mediaMetadata) @@ -661,61 +664,61 @@ public class SimpleBasePlayerTest { .setPeriods(periods) .build(); - assertThat(playlistItem.uid).isEqualTo(uid); - assertThat(playlistItem.tracks).isEqualTo(tracks); - assertThat(playlistItem.mediaItem).isEqualTo(mediaItem); - assertThat(playlistItem.mediaMetadata).isEqualTo(mediaMetadata); - assertThat(playlistItem.manifest).isEqualTo(manifest); - assertThat(playlistItem.liveConfiguration).isEqualTo(liveConfiguration); - assertThat(playlistItem.presentationStartTimeMs).isEqualTo(12); - assertThat(playlistItem.windowStartTimeMs).isEqualTo(23); - assertThat(playlistItem.elapsedRealtimeEpochOffsetMs).isEqualTo(10234); - assertThat(playlistItem.isSeekable).isTrue(); - assertThat(playlistItem.isDynamic).isTrue(); - assertThat(playlistItem.defaultPositionUs).isEqualTo(456_789); - assertThat(playlistItem.durationUs).isEqualTo(500_000); - assertThat(playlistItem.positionInFirstPeriodUs).isEqualTo(100_000); - assertThat(playlistItem.isPlaceholder).isTrue(); - assertThat(playlistItem.periods).isEqualTo(periods); + assertThat(mediaItemData.uid).isEqualTo(uid); + assertThat(mediaItemData.tracks).isEqualTo(tracks); + assertThat(mediaItemData.mediaItem).isEqualTo(mediaItem); + assertThat(mediaItemData.mediaMetadata).isEqualTo(mediaMetadata); + assertThat(mediaItemData.manifest).isEqualTo(manifest); + assertThat(mediaItemData.liveConfiguration).isEqualTo(liveConfiguration); + assertThat(mediaItemData.presentationStartTimeMs).isEqualTo(12); + assertThat(mediaItemData.windowStartTimeMs).isEqualTo(23); + assertThat(mediaItemData.elapsedRealtimeEpochOffsetMs).isEqualTo(10234); + assertThat(mediaItemData.isSeekable).isTrue(); + assertThat(mediaItemData.isDynamic).isTrue(); + assertThat(mediaItemData.defaultPositionUs).isEqualTo(456_789); + assertThat(mediaItemData.durationUs).isEqualTo(500_000); + assertThat(mediaItemData.positionInFirstPeriodUs).isEqualTo(100_000); + assertThat(mediaItemData.isPlaceholder).isTrue(); + assertThat(mediaItemData.periods).isEqualTo(periods); } @Test - public void playlistItemBuilderBuild_presentationStartTimeIfNotLive_throwsException() { + public void mediaItemDataBuilderBuild_presentationStartTimeIfNotLive_throwsException() { assertThrows( IllegalArgumentException.class, () -> - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setPresentationStartTimeMs(12) .build()); } @Test - public void playlistItemBuilderBuild_windowStartTimeIfNotLive_throwsException() { + public void mediaItemDataBuilderBuild_windowStartTimeIfNotLive_throwsException() { assertThrows( IllegalArgumentException.class, () -> - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setWindowStartTimeMs(12) .build()); } @Test - public void playlistItemBuilderBuild_elapsedEpochOffsetIfNotLive_throwsException() { + public void mediaItemDataBuilderBuild_elapsedEpochOffsetIfNotLive_throwsException() { assertThrows( IllegalArgumentException.class, () -> - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setElapsedRealtimeEpochOffsetMs(12) .build()); } @Test public void - playlistItemBuilderBuild_windowStartTimeLessThanPresentationStartTime_throwsException() { + mediaItemDataBuilderBuild_windowStartTimeLessThanPresentationStartTime_throwsException() { assertThrows( IllegalArgumentException.class, () -> - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setLiveConfiguration(MediaItem.LiveConfiguration.UNSET) .setWindowStartTimeMs(12) .setPresentationStartTimeMs(13) @@ -723,13 +726,13 @@ public class SimpleBasePlayerTest { } @Test - public void playlistItemBuilderBuild_multiplePeriodsWithSameUid_throwsException() { + public void mediaItemDataBuilderBuild_multiplePeriodsWithSameUid_throwsException() { Object uid = new Object(); assertThrows( IllegalArgumentException.class, () -> - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setPeriods( ImmutableList.of( new SimpleBasePlayer.PeriodData.Builder(uid).build(), @@ -738,11 +741,11 @@ public class SimpleBasePlayerTest { } @Test - public void playlistItemBuilderBuild_defaultPositionGreaterThanDuration_throwsException() { + public void mediaItemDataBuilderBuild_defaultPositionGreaterThanDuration_throwsException() { assertThrows( IllegalArgumentException.class, () -> - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setDefaultPositionUs(16) .setDurationUs(15) .build()); @@ -752,7 +755,7 @@ public class SimpleBasePlayerTest { public void periodDataBuilderBuild_setsCorrectValues() { Object uid = new Object(); AdPlaybackState adPlaybackState = - new AdPlaybackState(/* adsId= */ new Object(), /* adGroupTimesUs= */ 555, 666); + new AdPlaybackState(/* adsId= */ new Object(), /* adGroupTimesUs...= */ 555, 666); SimpleBasePlayer.PeriodData periodData = new SimpleBasePlayer.PeriodData.Builder(uid) @@ -795,7 +798,7 @@ public class SimpleBasePlayerTest { SimpleBasePlayer.PositionSupplier contentPositionSupplier = () -> 456; SimpleBasePlayer.PositionSupplier contentBufferedPositionSupplier = () -> 499; SimpleBasePlayer.PositionSupplier totalBufferedPositionSupplier = () -> 567; - Object playlistItemUid = new Object(); + Object mediaItemUid = new Object(); Object periodUid = new Object(); Tracks tracks = new Tracks( @@ -811,10 +814,10 @@ public class SimpleBasePlayerTest { Size surfaceSize = new Size(480, 360); MediaItem.LiveConfiguration liveConfiguration = new MediaItem.LiveConfiguration.Builder().setTargetOffsetMs(2000).build(); - ImmutableList playlist = + ImmutableList playlist = ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build(), - new SimpleBasePlayer.PlaylistItem.Builder(playlistItemUid) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid) .setTracks(tracks) .setMediaItem(mediaItem) .setMediaMetadata(mediaMetadata) @@ -836,7 +839,7 @@ public class SimpleBasePlayerTest { .setDurationUs(600_000) .setAdPlaybackState( new AdPlaybackState( - /* adsId= */ new Object(), /* adGroupTimesUs= */ 555, 666)) + /* adsId= */ new Object(), /* adGroupTimesUs...= */ 555, 666)) .build())) .build()); State state = @@ -955,7 +958,7 @@ public class SimpleBasePlayerTest { assertThat(window.liveConfiguration).isEqualTo(liveConfiguration); assertThat(window.manifest).isEqualTo(manifest); assertThat(window.mediaItem).isEqualTo(mediaItem); - assertThat(window.uid).isEqualTo(playlistItemUid); + assertThat(window.uid).isEqualTo(mediaItemUid); Timeline.Period period = timeline.getPeriod(/* periodIndex= */ 0, new Timeline.Period(), /* setIds= */ true); assertThat(period.durationUs).isEqualTo(C.TIME_UNSET); @@ -981,10 +984,10 @@ public class SimpleBasePlayerTest { SimpleBasePlayer.PositionSupplier totalBufferedPositionSupplier = () -> 567; SimpleBasePlayer.PositionSupplier adPositionSupplier = () -> 321; SimpleBasePlayer.PositionSupplier adBufferedPositionSupplier = () -> 345; - ImmutableList playlist = + ImmutableList playlist = ImmutableList.of( - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build(), - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()) + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .setDurationUs(500_000) .setPeriods( ImmutableList.of( @@ -993,7 +996,9 @@ public class SimpleBasePlayerTest { .setDurationUs(600_000) .setAdPlaybackState( new AdPlaybackState( - /* adsId= */ new Object(), /* adGroupTimesUs= */ 555, 666) + /* adsId= */ new Object(), /* adGroupTimesUs...= */ + 555, + 666) .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1) .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1) .withAdDurationsUs( @@ -1058,8 +1063,8 @@ public class SimpleBasePlayerTest { public void invalidateState_updatesStateAndInformsListeners() throws Exception { Object mediaItemUid0 = new Object(); MediaItem mediaItem0 = new MediaItem.Builder().setMediaId("0").build(); - SimpleBasePlayer.PlaylistItem playlistItem0 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid0).setMediaItem(mediaItem0).build(); + SimpleBasePlayer.MediaItemData mediaItemData0 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid0).setMediaItem(mediaItem0).build(); State state1 = new State.Builder() .setAvailableCommands(new Commands.Builder().addAllCommands().build()) @@ -1085,7 +1090,7 @@ public class SimpleBasePlayerTest { .setDeviceInfo(DeviceInfo.UNKNOWN) .setDeviceVolume(0) .setIsDeviceMuted(false) - .setPlaylist(ImmutableList.of(playlistItem0)) + .setPlaylist(ImmutableList.of(mediaItemData0)) .setPlaylistMetadata(MediaMetadata.EMPTY) .setCurrentMediaItemIndex(0) .setContentPositionMs(8_000) @@ -1101,8 +1106,8 @@ public class SimpleBasePlayerTest { /* adaptiveSupported= */ true, /* trackSupport= */ new int[] {C.FORMAT_HANDLED}, /* trackSelected= */ new boolean[] {true}))); - SimpleBasePlayer.PlaylistItem playlistItem1 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid1) + SimpleBasePlayer.MediaItemData mediaItemData1 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid1) .setMediaItem(mediaItem1) .setMediaMetadata(mediaMetadata) .setTracks(tracks) @@ -1163,7 +1168,7 @@ public class SimpleBasePlayerTest { .setSurfaceSize(surfaceSize) .setNewlyRenderedFirstFrame(true) .setTimedMetadata(timedMetadata) - .setPlaylist(ImmutableList.of(playlistItem0, playlistItem1)) + .setPlaylist(ImmutableList.of(mediaItemData0, mediaItemData1)) .setPlaylistMetadata(playlistMetadata) .setCurrentMediaItemIndex(1) .setContentPositionMs(12_000) @@ -1304,20 +1309,20 @@ public class SimpleBasePlayerTest { } @Test - public void invalidateState_withPlaylistItemDetailChange_reportsTimelineSourceUpdate() { + public void invalidateState_withMediaItemDetailChange_reportsTimelineSourceUpdate() { Object mediaItemUid0 = new Object(); - SimpleBasePlayer.PlaylistItem playlistItem0 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid0).build(); + SimpleBasePlayer.MediaItemData mediaItemData0 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid0).build(); Object mediaItemUid1 = new Object(); - SimpleBasePlayer.PlaylistItem playlistItem1 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid1).build(); + SimpleBasePlayer.MediaItemData mediaItemData1 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid1).build(); State state1 = - new State.Builder().setPlaylist(ImmutableList.of(playlistItem0, playlistItem1)).build(); - SimpleBasePlayer.PlaylistItem playlistItem1Updated = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid1).setDurationUs(10_000).build(); + new State.Builder().setPlaylist(ImmutableList.of(mediaItemData0, mediaItemData1)).build(); + SimpleBasePlayer.MediaItemData mediaItemData1Updated = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid1).setDurationUs(10_000).build(); State state2 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem0, playlistItem1Updated)) + .setPlaylist(ImmutableList.of(mediaItemData0, mediaItemData1Updated)) .build(); AtomicBoolean returnState2 = new AtomicBoolean(); SimpleBasePlayer player = @@ -1343,21 +1348,21 @@ public class SimpleBasePlayerTest { public void invalidateState_withCurrentMediaItemRemoval_reportsDiscontinuityReasonRemoved() { Object mediaItemUid0 = new Object(); MediaItem mediaItem0 = new MediaItem.Builder().setMediaId("0").build(); - SimpleBasePlayer.PlaylistItem playlistItem0 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid0).setMediaItem(mediaItem0).build(); + SimpleBasePlayer.MediaItemData mediaItemData0 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid0).setMediaItem(mediaItem0).build(); Object mediaItemUid1 = new Object(); MediaItem mediaItem1 = new MediaItem.Builder().setMediaId("1").build(); - SimpleBasePlayer.PlaylistItem playlistItem1 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid1).setMediaItem(mediaItem1).build(); + SimpleBasePlayer.MediaItemData mediaItemData1 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid1).setMediaItem(mediaItem1).build(); State state1 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem0, playlistItem1)) + .setPlaylist(ImmutableList.of(mediaItemData0, mediaItemData1)) .setCurrentMediaItemIndex(1) .setContentPositionMs(5000) .build(); State state2 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem0)) + .setPlaylist(ImmutableList.of(mediaItemData0)) .setCurrentMediaItemIndex(0) .setContentPositionMs(2000) .build(); @@ -1409,24 +1414,24 @@ public class SimpleBasePlayerTest { invalidateState_withTransitionFromEndOfItem_reportsDiscontinuityReasonAutoTransition() { Object mediaItemUid0 = new Object(); MediaItem mediaItem0 = new MediaItem.Builder().setMediaId("0").build(); - SimpleBasePlayer.PlaylistItem playlistItem0 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid0) + SimpleBasePlayer.MediaItemData mediaItemData0 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid0) .setMediaItem(mediaItem0) .setDurationUs(50_000) .build(); Object mediaItemUid1 = new Object(); MediaItem mediaItem1 = new MediaItem.Builder().setMediaId("1").build(); - SimpleBasePlayer.PlaylistItem playlistItem1 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid1).setMediaItem(mediaItem1).build(); + SimpleBasePlayer.MediaItemData mediaItemData1 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid1).setMediaItem(mediaItem1).build(); State state1 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem0, playlistItem1)) + .setPlaylist(ImmutableList.of(mediaItemData0, mediaItemData1)) .setCurrentMediaItemIndex(0) .setContentPositionMs(50) .build(); State state2 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem0, playlistItem1)) + .setPlaylist(ImmutableList.of(mediaItemData0, mediaItemData1)) .setCurrentMediaItemIndex(1) .setContentPositionMs(10) .build(); @@ -1476,24 +1481,24 @@ public class SimpleBasePlayerTest { public void invalidateState_withTransitionFromMiddleOfItem_reportsDiscontinuityReasonSkip() { Object mediaItemUid0 = new Object(); MediaItem mediaItem0 = new MediaItem.Builder().setMediaId("0").build(); - SimpleBasePlayer.PlaylistItem playlistItem0 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid0) + SimpleBasePlayer.MediaItemData mediaItemData0 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid0) .setMediaItem(mediaItem0) .setDurationUs(50_000) .build(); Object mediaItemUid1 = new Object(); MediaItem mediaItem1 = new MediaItem.Builder().setMediaId("1").build(); - SimpleBasePlayer.PlaylistItem playlistItem1 = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid1).setMediaItem(mediaItem1).build(); + SimpleBasePlayer.MediaItemData mediaItemData1 = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid1).setMediaItem(mediaItem1).build(); State state1 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem0, playlistItem1)) + .setPlaylist(ImmutableList.of(mediaItemData0, mediaItemData1)) .setCurrentMediaItemIndex(0) .setContentPositionMs(20) .build(); State state2 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem0, playlistItem1)) + .setPlaylist(ImmutableList.of(mediaItemData0, mediaItemData1)) .setCurrentMediaItemIndex(1) .setContentPositionMs(10) .build(); @@ -1544,20 +1549,20 @@ public class SimpleBasePlayerTest { public void invalidateState_withRepeatingItem_reportsDiscontinuityReasonAutoTransition() { Object mediaItemUid = new Object(); MediaItem mediaItem = new MediaItem.Builder().setMediaId("0").build(); - SimpleBasePlayer.PlaylistItem playlistItem = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid) + SimpleBasePlayer.MediaItemData mediaItemData = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid) .setMediaItem(mediaItem) .setDurationUs(5_000_000) .build(); State state1 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem)) + .setPlaylist(ImmutableList.of(mediaItemData)) .setCurrentMediaItemIndex(0) .setContentPositionMs(5_000) .build(); State state2 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem)) + .setPlaylist(ImmutableList.of(mediaItemData)) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build(); @@ -1607,20 +1612,20 @@ public class SimpleBasePlayerTest { public void invalidateState_withDiscontinuityInsideItem_reportsDiscontinuityReasonInternal() { Object mediaItemUid = new Object(); MediaItem mediaItem = new MediaItem.Builder().setMediaId("0").build(); - SimpleBasePlayer.PlaylistItem playlistItem = - new SimpleBasePlayer.PlaylistItem.Builder(mediaItemUid) + SimpleBasePlayer.MediaItemData mediaItemData = + new SimpleBasePlayer.MediaItemData.Builder(mediaItemUid) .setMediaItem(mediaItem) .setDurationUs(5_000_000) .build(); State state1 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem)) + .setPlaylist(ImmutableList.of(mediaItemData)) .setCurrentMediaItemIndex(0) .setContentPositionMs(1_000) .build(); State state2 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem)) + .setPlaylist(ImmutableList.of(mediaItemData)) .setCurrentMediaItemIndex(0) .setContentPositionMs(3_000) .build(); @@ -1668,17 +1673,17 @@ public class SimpleBasePlayerTest { @Test public void invalidateState_withMinorPositionDrift_doesNotReportsDiscontinuity() { - SimpleBasePlayer.PlaylistItem playlistItem = - new SimpleBasePlayer.PlaylistItem.Builder(/* uid= */ new Object()).build(); + SimpleBasePlayer.MediaItemData mediaItemData = + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(); State state1 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem)) + .setPlaylist(ImmutableList.of(mediaItemData)) .setCurrentMediaItemIndex(0) .setContentPositionMs(1_000) .build(); State state2 = new State.Builder() - .setPlaylist(ImmutableList.of(playlistItem)) + .setPlaylist(ImmutableList.of(mediaItemData)) .setCurrentMediaItemIndex(0) .setContentPositionMs(1_500) .build(); From ed20420b9b56d6bdbc5456f937d4390cb9417bd9 Mon Sep 17 00:00:00 2001 From: kimvde Date: Wed, 30 Nov 2022 17:05:41 +0000 Subject: [PATCH 028/183] Move audio decoding to AssetLoader PiperOrigin-RevId: 491933937 --- .../AudioTranscodingSamplePipeline.java | 77 ++++++----- .../transformer/ExoPlayerAssetLoader.java | 14 +- .../ExoPlayerAssetLoaderRenderer.java | 120 ++++++++++++++++-- .../PassthroughSamplePipeline.java | 5 + .../transformer/SamplePipeline.java | 9 ++ .../transformer/TransformerInternal.java | 13 +- .../VideoTranscodingSamplePipeline.java | 5 + 7 files changed, 188 insertions(+), 55 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java index b6aada7114..918561d111 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java @@ -41,14 +41,14 @@ import org.checkerframework.dataflow.qual.Pure; private static final int DEFAULT_ENCODER_BITRATE = 128 * 1024; - private final Codec decoder; - private final DecoderInputBuffer decoderInputBuffer; + private final DecoderInputBuffer inputBuffer; private final AudioProcessingPipeline audioProcessingPipeline; private final Codec encoder; private final AudioFormat encoderInputAudioFormat; private final DecoderInputBuffer encoderInputBuffer; private final DecoderInputBuffer encoderOutputBuffer; + private boolean hasPendingInputBuffer; private long nextEncoderInputBufferTimeUs; private long encoderBufferDurationRemainder; @@ -58,7 +58,6 @@ import org.checkerframework.dataflow.qual.Pure; long streamOffsetUs, TransformationRequest transformationRequest, ImmutableList audioProcessors, - Codec.DecoderFactory decoderFactory, Codec.EncoderFactory encoderFactory, MuxerWrapper muxerWrapper, Listener listener, @@ -72,12 +71,10 @@ import org.checkerframework.dataflow.qual.Pure; muxerWrapper, listener); - decoderInputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); + inputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); encoderInputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); encoderOutputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); - decoder = decoderFactory.createForAudioDecoding(inputFormat); - if (transformationRequest.flattenForSlowMotion) { audioProcessors = new ImmutableList.Builder() @@ -139,30 +136,34 @@ import org.checkerframework.dataflow.qual.Pure; nextEncoderInputBufferTimeUs = streamOffsetUs; } + @Override + public boolean expectsDecodedData() { + return true; + } + @Override public void release() { audioProcessingPipeline.reset(); - decoder.release(); encoder.release(); } @Override @Nullable - protected DecoderInputBuffer dequeueInputBufferInternal() throws TransformationException { - return decoder.maybeDequeueInputBuffer(decoderInputBuffer) ? decoderInputBuffer : null; + protected DecoderInputBuffer dequeueInputBufferInternal() { + return hasPendingInputBuffer ? null : inputBuffer; } @Override - protected void queueInputBufferInternal() throws TransformationException { - decoder.queueInputBuffer(decoderInputBuffer); + protected void queueInputBufferInternal() { + hasPendingInputBuffer = true; } @Override protected boolean processDataUpToMuxer() throws TransformationException { if (audioProcessingPipeline.isOperational()) { - return feedEncoderFromProcessingPipeline() || feedProcessingPipelineFromDecoder(); + return feedEncoderFromProcessingPipeline() || feedProcessingPipelineFromInput(); } else { - return feedEncoderFromDecoder(); + return feedEncoderFromInput(); } } @@ -195,27 +196,25 @@ import org.checkerframework.dataflow.qual.Pure; } /** - * Attempts to pass decoder output data to the encoder, and returns whether it may be possible to - * pass more data immediately by calling this method again. + * Attempts to pass input data to the encoder. + * + * @return Whether it may be possible to feed more data immediately by calling this method again. */ - private boolean feedEncoderFromDecoder() throws TransformationException { - if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) { + private boolean feedEncoderFromInput() throws TransformationException { + if (!hasPendingInputBuffer || !encoder.maybeDequeueInputBuffer(encoderInputBuffer)) { return false; } - if (decoder.isEnded()) { + if (inputBuffer.isEndOfStream()) { queueEndOfStreamToEncoder(); + hasPendingInputBuffer = false; return false; } - @Nullable ByteBuffer decoderOutputBuffer = decoder.getOutputBuffer(); - if (decoderOutputBuffer == null) { - return false; - } - - feedEncoder(decoderOutputBuffer); - if (!decoderOutputBuffer.hasRemaining()) { - decoder.releaseOutputBuffer(/* render= */ false); + ByteBuffer inputData = checkNotNull(inputBuffer.data); + feedEncoder(inputData); + if (!inputData.hasRemaining()) { + hasPendingInputBuffer = false; } return true; } @@ -223,7 +222,7 @@ import org.checkerframework.dataflow.qual.Pure; /** * Attempts to feed audio processor output data to the encoder. * - * @return Whether more data can be fed immediately, by calling this method again. + * @return Whether it may be possible to feed more data immediately by calling this method again. */ private boolean feedEncoderFromProcessingPipeline() throws TransformationException { if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) { @@ -244,28 +243,28 @@ import org.checkerframework.dataflow.qual.Pure; } /** - * Attempts to feed decoder output data to the {@link AudioProcessingPipeline}. + * Attempts to feed input data to the {@link AudioProcessingPipeline}. * * @return Whether it may be possible to feed more data immediately by calling this method again. */ - private boolean feedProcessingPipelineFromDecoder() throws TransformationException { - if (decoder.isEnded()) { + private boolean feedProcessingPipelineFromInput() { + if (!hasPendingInputBuffer) { + return false; + } + + if (inputBuffer.isEndOfStream()) { audioProcessingPipeline.queueEndOfStream(); + hasPendingInputBuffer = false; return false; } checkState(!audioProcessingPipeline.isEnded()); - @Nullable ByteBuffer decoderOutputBuffer = decoder.getOutputBuffer(); - if (decoderOutputBuffer == null) { + ByteBuffer inputData = checkNotNull(inputBuffer.data); + audioProcessingPipeline.queueInput(inputData); + if (inputData.hasRemaining()) { return false; } - - audioProcessingPipeline.queueInput(decoderOutputBuffer); - if (decoderOutputBuffer.hasRemaining()) { - return false; - } - // Decoder output buffer was fully consumed by the processing pipeline. - decoder.releaseOutputBuffer(/* render= */ false); + hasPendingInputBuffer = false; return true; } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java index 7b48948a54..f79b0128cd 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoader.java @@ -69,6 +69,7 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; boolean removeAudio, boolean removeVideo, MediaSource.Factory mediaSourceFactory, + Codec.DecoderFactory decoderFactory, Looper looper, Listener listener, Clock clock) { @@ -89,7 +90,9 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS / 10) .build(); ExoPlayer.Builder playerBuilder = - new ExoPlayer.Builder(context, new RenderersFactoryImpl(removeAudio, removeVideo, listener)) + new ExoPlayer.Builder( + context, + new RenderersFactoryImpl(removeAudio, removeVideo, decoderFactory, listener)) .setMediaSourceFactory(mediaSourceFactory) .setTrackSelector(trackSelector) .setLoadControl(loadControl) @@ -120,14 +123,17 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; private final TransformerMediaClock mediaClock; private final boolean removeAudio; private final boolean removeVideo; + private final Codec.DecoderFactory decoderFactory; private final ExoPlayerAssetLoader.Listener assetLoaderListener; public RenderersFactoryImpl( boolean removeAudio, boolean removeVideo, + Codec.DecoderFactory decoderFactory, ExoPlayerAssetLoader.Listener assetLoaderListener) { this.removeAudio = removeAudio; this.removeVideo = removeVideo; + this.decoderFactory = decoderFactory; this.assetLoaderListener = assetLoaderListener; mediaClock = new TransformerMediaClock(); } @@ -144,12 +150,14 @@ import com.google.android.exoplayer2.video.VideoRendererEventListener; int index = 0; if (!removeAudio) { renderers[index] = - new ExoPlayerAssetLoaderRenderer(C.TRACK_TYPE_AUDIO, mediaClock, assetLoaderListener); + new ExoPlayerAssetLoaderRenderer( + C.TRACK_TYPE_AUDIO, decoderFactory, mediaClock, assetLoaderListener); index++; } if (!removeVideo) { renderers[index] = - new ExoPlayerAssetLoaderRenderer(C.TRACK_TYPE_VIDEO, mediaClock, assetLoaderListener); + new ExoPlayerAssetLoaderRenderer( + C.TRACK_TYPE_VIDEO, decoderFactory, mediaClock, assetLoaderListener); index++; } return renderers; diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderRenderer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderRenderer.java index 919faa2474..4726569186 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderRenderer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/ExoPlayerAssetLoaderRenderer.java @@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.decoder.DecoderInputBuffer.BUFFER_RE import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; +import android.media.MediaCodec; import androidx.annotation.Nullable; import com.google.android.exoplayer2.BaseRenderer; import com.google.android.exoplayer2.C; @@ -30,6 +31,7 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult; import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.MimeTypes; +import java.nio.ByteBuffer; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull; @@ -38,6 +40,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; private static final String TAG = "ExoPlayerAssetLoaderRenderer"; + private final Codec.DecoderFactory decoderFactory; private final TransformerMediaClock mediaClock; private final ExoPlayerAssetLoader.Listener assetLoaderListener; private final DecoderInputBuffer decoderInputBuffer; @@ -45,14 +48,18 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; private boolean isTransformationRunning; private long streamStartPositionUs; private long streamOffsetUs; + private @MonotonicNonNull Codec decoder; + @Nullable private ByteBuffer pendingDecoderOutputBuffer; private SamplePipeline.@MonotonicNonNull Input samplePipelineInput; private boolean isEnded; public ExoPlayerAssetLoaderRenderer( int trackType, + Codec.DecoderFactory decoderFactory, TransformerMediaClock mediaClock, ExoPlayerAssetLoader.Listener assetLoaderListener) { super(trackType); + this.decoderFactory = decoderFactory; this.mediaClock = mediaClock; this.assetLoaderListener = assetLoaderListener; decoderInputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); @@ -99,7 +106,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; return; } - while (feedPipelineFromInput()) {} + if (samplePipelineInput.expectsDecodedData()) { + while (feedPipelineFromDecoder() || feedDecoderFromInput()) {} + } else { + while (feedPipelineFromInput()) {} + } } catch (TransformationException e) { isTransformationRunning = false; assetLoaderListener.onError(e); @@ -128,6 +139,13 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; isTransformationRunning = false; } + @Override + protected void onReset() { + if (decoder != null) { + decoder.release(); + } + } + @EnsuresNonNullIf(expression = "samplePipelineInput", result = true) private boolean ensureConfigured() throws TransformationException { if (samplePipelineInput != null) { @@ -143,6 +161,74 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; Format inputFormat = checkNotNull(formatHolder.format); samplePipelineInput = assetLoaderListener.onTrackAdded(inputFormat, streamStartPositionUs, streamOffsetUs); + if (samplePipelineInput.expectsDecodedData()) { + decoder = decoderFactory.createForAudioDecoding(inputFormat); + } + return true; + } + + /** + * Attempts to read decoded data and pass it to the sample pipeline. + * + * @return Whether it may be possible to read more data immediately by calling this method again. + * @throws TransformationException If an error occurs in the decoder or in the {@link + * SamplePipeline}. + */ + @RequiresNonNull("samplePipelineInput") + private boolean feedPipelineFromDecoder() throws TransformationException { + @Nullable + DecoderInputBuffer samplePipelineInputBuffer = samplePipelineInput.dequeueInputBuffer(); + if (samplePipelineInputBuffer == null) { + return false; + } + + Codec decoder = checkNotNull(this.decoder); + if (pendingDecoderOutputBuffer != null) { + if (pendingDecoderOutputBuffer.hasRemaining()) { + return false; + } else { + decoder.releaseOutputBuffer(/* render= */ false); + pendingDecoderOutputBuffer = null; + } + } + + if (decoder.isEnded()) { + samplePipelineInputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); + samplePipelineInput.queueInputBuffer(); + isEnded = true; + return false; + } + + pendingDecoderOutputBuffer = decoder.getOutputBuffer(); + if (pendingDecoderOutputBuffer == null) { + return false; + } + + samplePipelineInputBuffer.data = pendingDecoderOutputBuffer; + MediaCodec.BufferInfo bufferInfo = checkNotNull(decoder.getOutputBufferInfo()); + samplePipelineInputBuffer.timeUs = bufferInfo.presentationTimeUs; + samplePipelineInputBuffer.setFlags(bufferInfo.flags); + samplePipelineInput.queueInputBuffer(); + return true; + } + + /** + * Attempts to read input data and pass it to the decoder. + * + * @return Whether it may be possible to read more data immediately by calling this method again. + * @throws TransformationException If an error occurs in the decoder. + */ + private boolean feedDecoderFromInput() throws TransformationException { + Codec decoder = checkNotNull(this.decoder); + if (!decoder.maybeDequeueInputBuffer(decoderInputBuffer)) { + return false; + } + + if (!readInput(decoderInputBuffer)) { + return false; + } + + decoder.queueInputBuffer(decoderInputBuffer); return true; } @@ -159,18 +245,32 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; return false; } - @ReadDataResult - int result = readSource(getFormatHolder(), samplePipelineInputBuffer, /* readFlags= */ 0); + if (!readInput(samplePipelineInputBuffer)) { + return false; + } + + samplePipelineInput.queueInputBuffer(); + if (samplePipelineInputBuffer.isEndOfStream()) { + isEnded = true; + return false; + } + return true; + } + + /** + * Attempts to populate {@code buffer} with input data. + * + * @param buffer The buffer to populate. + * @return Whether the {@code buffer} has been populated. + */ + private boolean readInput(DecoderInputBuffer buffer) { + @ReadDataResult int result = readSource(getFormatHolder(), buffer, /* readFlags= */ 0); switch (result) { case C.RESULT_BUFFER_READ: - samplePipelineInputBuffer.flip(); - if (samplePipelineInputBuffer.isEndOfStream()) { - samplePipelineInput.queueInputBuffer(); - isEnded = true; - return false; + buffer.flip(); + if (!buffer.isEndOfStream()) { + mediaClock.updateTimeForTrackType(getTrackType(), buffer.timeUs); } - mediaClock.updateTimeForTrackType(getTrackType(), samplePipelineInputBuffer.timeUs); - samplePipelineInput.queueInputBuffer(); return true; case C.RESULT_FORMAT_READ: throw new IllegalStateException("Format changes are not supported."); diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/PassthroughSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/PassthroughSamplePipeline.java index a210b5c842..b1bcc24d67 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/PassthroughSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/PassthroughSamplePipeline.java @@ -48,6 +48,11 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; fallbackListener.onTransformationRequestFinalized(transformationRequest); } + @Override + public boolean expectsDecodedData() { + return false; + } + @Override public void release() {} diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java index e789ce9149..a4f3382d6d 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java @@ -29,6 +29,9 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; /** Input of a {@link SamplePipeline}. */ interface Input { + /** See {@link SamplePipeline#expectsDecodedData()}. */ + boolean expectsDecodedData(); + /** See {@link SamplePipeline#dequeueInputBuffer()}. */ @Nullable DecoderInputBuffer dequeueInputBuffer(); @@ -56,6 +59,12 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; void onTransformationError(TransformationException exception); } + /** + * Returns whether the pipeline should be fed with decoded sample data. If false, encoded sample + * data should be queued. + */ + boolean expectsDecodedData(); + /** Returns a buffer if the pipeline is ready to accept input, and {@code null} otherwise. */ @Nullable DecoderInputBuffer dequeueInputBuffer() throws TransformationException; diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java index dd3360b6d7..30216dcac6 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java @@ -163,6 +163,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; removeAudio, removeVideo, mediaSourceFactory, + decoderFactory, internalLooper, componentListener, clock); @@ -409,7 +410,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; int samplePipelineIndex = tracksAddedCount; tracksAddedCount++; - return new SamplePipelineInput(samplePipelineIndex); + return new SamplePipelineInput(samplePipelineIndex, samplePipeline.expectsDecodedData()); } @Override @@ -458,7 +459,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; streamOffsetUs, transformationRequest, audioProcessors, - decoderFactory, encoderFactory, muxerWrapper, /* listener= */ this, @@ -573,9 +573,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private class SamplePipelineInput implements SamplePipeline.Input { private final int samplePipelineIndex; + private final boolean expectsDecodedData; - public SamplePipelineInput(int samplePipelineIndex) { + public SamplePipelineInput(int samplePipelineIndex, boolean expectsDecodedData) { this.samplePipelineIndex = samplePipelineIndex; + this.expectsDecodedData = expectsDecodedData; + } + + @Override + public boolean expectsDecodedData() { + return expectsDecodedData; } @Nullable diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java index 79f78b429d..a6937b9193 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java @@ -207,6 +207,11 @@ import org.checkerframework.dataflow.qual.Pure; maxPendingFrameCount = decoder.getMaxPendingFrameCount(); } + @Override + public boolean expectsDecodedData() { + return false; + } + @Override public void release() { frameProcessor.release(); From c308802ad159412a5505ba843a20991d9cd59967 Mon Sep 17 00:00:00 2001 From: claincly Date: Wed, 30 Nov 2022 18:38:45 +0000 Subject: [PATCH 029/183] Add function to clear the cached list of encoders EncoderUtil using a static list to cache encoders means it's not possible to use a different set of encoders for different tests when running all robolectric tests together. PiperOrigin-RevId: 491959350 --- .../exoplayer2/transformer/EncoderUtil.java | 38 +++++++++++-------- .../DefaultEncoderFactoryTest.java | 9 +++++ .../transformer/EncoderUtilTest.java | 9 +++++ .../transformer/TransformerEndToEndTest.java | 2 + .../transformer/VideoEncoderWrapperTest.java | 9 +++++ 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java index ee422166cd..0218c199fb 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java @@ -16,7 +16,6 @@ package com.google.android.exoplayer2.transformer; -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static java.lang.Math.max; import static java.lang.Math.round; @@ -29,8 +28,10 @@ import android.util.Pair; import android.util.Range; import android.util.Size; import androidx.annotation.DoNotInline; +import androidx.annotation.GuardedBy; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C.ColorTransfer; import com.google.android.exoplayer2.Format; @@ -39,10 +40,8 @@ import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.ColorInfo; import com.google.common.base.Ascii; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; +import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.primitives.Ints; @@ -52,20 +51,29 @@ public final class EncoderUtil { /** A value to indicate the encoding level is not set. */ public static final int LEVEL_UNSET = Format.NO_VALUE; - private static final Supplier> - MIME_TYPE_TO_ENCODERS = Suppliers.memoize(EncoderUtil::populateEncoderInfos); + @GuardedBy("EncoderUtil.class") + private static final ArrayListMultimap mimeTypeToEncoders = + ArrayListMultimap.create(); /** * Returns a list of {@linkplain MediaCodecInfo encoders} that support the given {@code mimeType}, * or an empty list if there is none. */ - public static ImmutableList getSupportedEncoders(String mimeType) { - return checkNotNull(MIME_TYPE_TO_ENCODERS.get()).get(Ascii.toLowerCase(mimeType)); + public static synchronized ImmutableList getSupportedEncoders(String mimeType) { + maybePopulateEncoderInfo(); + return ImmutableList.copyOf(mimeTypeToEncoders.get(Ascii.toLowerCase(mimeType))); } /** Returns a list of video {@linkplain MimeTypes MIME types} that can be encoded. */ - public static ImmutableSet getSupportedVideoMimeTypes() { - return checkNotNull(MIME_TYPE_TO_ENCODERS.get()).keySet(); + public static synchronized ImmutableSet getSupportedVideoMimeTypes() { + maybePopulateEncoderInfo(); + return ImmutableSet.copyOf(mimeTypeToEncoders.keySet()); + } + + /** Clears the cached list of encoders. */ + @VisibleForTesting + public static synchronized void clearCachedEncoders() { + mimeTypeToEncoders.clear(); } /** @@ -431,9 +439,10 @@ public final class EncoderUtil { : alignment * Math.round((float) size / alignment); } - private static ImmutableListMultimap populateEncoderInfos() { - ImmutableListMultimap.Builder encoderInfosBuilder = - new ImmutableListMultimap.Builder<>(); + private static synchronized void maybePopulateEncoderInfo() { + if (!mimeTypeToEncoders.isEmpty()) { + return; + } MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); MediaCodecInfo[] allCodecInfos = mediaCodecList.getCodecInfos(); @@ -444,10 +453,9 @@ public final class EncoderUtil { } String[] supportedMimeTypes = mediaCodecInfo.getSupportedTypes(); for (String mimeType : supportedMimeTypes) { - encoderInfosBuilder.put(Ascii.toLowerCase(mimeType), mediaCodecInfo); + mimeTypeToEncoders.put(Ascii.toLowerCase(mimeType), mediaCodecInfo); } } - return encoderInfosBuilder.build(); } @RequiresApi(29) diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java index d280d94544..68c80b359e 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java @@ -28,11 +28,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.MimeTypes; import com.google.common.collect.ImmutableList; +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.ShadowMediaCodec; import org.robolectric.shadows.ShadowMediaCodecList; /** Unit test for {@link DefaultEncoderFactory}. */ @@ -45,6 +47,13 @@ public class DefaultEncoderFactoryTest { createShadowH264Encoder(); } + @After + public void tearDown() { + ShadowMediaCodec.clearCodecs(); + ShadowMediaCodecList.reset(); + EncoderUtil.clearCachedEncoders(); + } + private static void createShadowH264Encoder() { MediaFormat avcFormat = new MediaFormat(); avcFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC); diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/EncoderUtilTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/EncoderUtilTest.java index 56eb3e8ef1..5304c4f409 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/EncoderUtilTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/EncoderUtilTest.java @@ -27,11 +27,13 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.video.ColorInfo; import com.google.common.collect.ImmutableList; +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.ShadowMediaCodec; import org.robolectric.shadows.ShadowMediaCodecList; /** Unit test for {@link EncoderUtil}. */ @@ -64,6 +66,13 @@ public class EncoderUtilTest { .build()); } + @After + public void tearDown() { + ShadowMediaCodecList.reset(); + ShadowMediaCodec.clearCodecs(); + EncoderUtil.clearCachedEncoders(); + } + @Test public void getSupportedResolution_withSupportedResolution_succeeds() { ImmutableList supportedEncoders = EncoderUtil.getSupportedEncoders(MIME_TYPE); diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index 0a16ff5b61..7b9ce8c343 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -898,6 +898,8 @@ public final class TransformerEndToEndTest { private static void removeEncodersAndDecoders() { ShadowMediaCodec.clearCodecs(); + ShadowMediaCodecList.reset(); + EncoderUtil.clearCachedEncoders(); } private static String getDumpFileName(String originalFileName) { diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java index f187aa370c..58a10c6380 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java @@ -32,10 +32,12 @@ import com.google.android.exoplayer2.util.ListenerSet; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.SurfaceInfo; import com.google.common.collect.ImmutableList; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.shadows.MediaCodecInfoBuilder; +import org.robolectric.shadows.ShadowMediaCodec; import org.robolectric.shadows.ShadowMediaCodecList; /** Unit tests for {@link VideoTranscodingSamplePipeline.EncoderWrapper}. */ @@ -63,6 +65,13 @@ public final class VideoEncoderWrapperTest { createShadowH264Encoder(); } + @After + public void tearDown() { + ShadowMediaCodec.clearCodecs(); + ShadowMediaCodecList.reset(); + EncoderUtil.clearCachedEncoders(); + } + @Test public void getSurfaceInfo_landscape_leavesOrientationUnchanged() throws Exception { int inputWidth = 200; From 749d77b1d9989d091dc11269087093bc2c48d216 Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 30 Nov 2022 18:54:31 +0000 Subject: [PATCH 030/183] Make PlayerView fold aware PiperOrigin-RevId: 491963883 --- constants.gradle | 1 + library/ui/build.gradle | 2 + .../exoplayer2/ui/StyledPlayerView.java | 84 +++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/constants.gradle b/constants.gradle index 3068e7646b..3840bb533f 100644 --- a/constants.gradle +++ b/constants.gradle @@ -54,6 +54,7 @@ project.ext { androidxTestRulesVersion = '1.4.0' androidxTestServicesStorageVersion = '1.4.0' androidxTestTruthVersion = '1.4.0' + androidxWindowVersion = '1.0.0' truthVersion = '1.1.3' okhttpVersion = '4.9.2' modulePrefix = ':' diff --git a/library/ui/build.gradle b/library/ui/build.gradle index 7b21db436e..c7c990069d 100644 --- a/library/ui/build.gradle +++ b/library/ui/build.gradle @@ -25,7 +25,9 @@ dependencies { implementation project(modulePrefix + 'library-common') api 'androidx.media:media:' + androidxMediaVersion implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion + implementation 'androidx.core:core:' + androidxCoreVersion implementation 'androidx.recyclerview:recyclerview:' + androidxRecyclerViewVersion + implementation 'androidx.window:window:' + androidxWindowVersion compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion testImplementation project(modulePrefix + 'testutils') 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 da17c4c1c7..3f5d2dd28f 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 @@ -21,7 +21,10 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static java.lang.annotation.ElementType.TYPE_USE; import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; +import android.content.ContextWrapper; +import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; @@ -48,6 +51,14 @@ import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.core.content.ContextCompat; +import androidx.core.util.Consumer; +import androidx.window.java.layout.WindowInfoTrackerCallbackAdapter; +import androidx.window.layout.DisplayFeature; +import androidx.window.layout.FoldingFeature; +import androidx.window.layout.FoldingFeature.Orientation; +import androidx.window.layout.FoldingFeature.State; +import androidx.window.layout.WindowInfoTracker; +import androidx.window.layout.WindowLayoutInfo; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.MediaMetadata; import com.google.android.exoplayer2.PlaybackException; @@ -71,6 +82,7 @@ import java.lang.annotation.Target; import java.util.ArrayList; import java.util.List; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** @@ -258,6 +270,9 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { private boolean controllerHideOnTouch; private int textureViewRotation; private boolean isTouching; + private boolean isTabletop; + private final WindowInfoTrackerCallbackAdapter windowInfoTracker; + @MonotonicNonNull private Consumer layoutStateChangeCallback; public StyledPlayerView(Context context) { this(context, /* attrs= */ null); @@ -271,6 +286,9 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { public StyledPlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + isTabletop = false; + windowInfoTracker = + new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(context)); componentListener = new ComponentListener(); if (isInEditMode()) { @@ -572,6 +590,25 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { } } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + layoutStateChangeCallback = this::consumeWindowLayoutInfo; + @Nullable Activity activity = getActivity(); + if (activity != null) { + windowInfoTracker.addWindowLayoutInfoListener( + activity, ContextCompat.getMainExecutor(getContext()), layoutStateChangeCallback); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (layoutStateChangeCallback != null) { + windowInfoTracker.removeWindowLayoutInfoListener(layoutStateChangeCallback); + } + } + /** * Sets the {@link ResizeMode}. * @@ -1466,6 +1503,53 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider { || keyCode == KeyEvent.KEYCODE_DPAD_CENTER; } + @Nullable + private Activity getActivity() { + Context context = getContext(); + while (context instanceof ContextWrapper) { + if (context instanceof Activity) { + return (Activity) context; + } + context = ((ContextWrapper) context).getBaseContext(); + } + return null; + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + isTabletop = false; + } + + private void consumeWindowLayoutInfo(WindowLayoutInfo windowLayoutInfo) { + List features = windowLayoutInfo.getDisplayFeatures(); + int foldingFeatureIndex = C.INDEX_UNSET; + + for (int i = 0; i < features.size(); i++) { + DisplayFeature feature = features.get(i); + if (feature instanceof FoldingFeature) { + if (foldingFeatureIndex != C.INDEX_UNSET) { + // For now, we are only handling single folding features like tabletop and book fold. + return; + } + foldingFeatureIndex = i; + } + } + if (foldingFeatureIndex != C.INDEX_UNSET) { + handleFoldingFeature((FoldingFeature) features.get(foldingFeatureIndex)); + } + } + + private void handleFoldingFeature(FoldingFeature feature) { + boolean isTabletopFeature = + feature.getOrientation() == Orientation.HORIZONTAL + && feature.getState() == State.HALF_OPENED; + // Only enter or exit tabletop if different than current orientation and state + if (isTabletopFeature != isTabletop) { + isTabletop = isTabletopFeature; + } + } + // Implementing the deprecated StyledPlayerControlView.VisibilityListener and // StyledPlayerControlView.OnFullScreenModeChangedListener for now. @SuppressWarnings("deprecation") From 2652d0efd7c02e541b2a6a9f8ca276364953e765 Mon Sep 17 00:00:00 2001 From: huangdarwin Date: Wed, 30 Nov 2022 20:13:32 +0000 Subject: [PATCH 031/183] Transformer: Move getMaxPendingFrameCount logic to constructor. Also, use the mediaCodecName passed into the constructor to get the maxPendingFrameCount. PiperOrigin-RevId: 491985044 --- .../exoplayer2/transformer/DefaultCodec.java | 75 ++++++++++--------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java index 470aaf7bf3..a8fcffeaa5 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java @@ -64,8 +64,7 @@ public final class DefaultCodec implements Codec { private final Format configurationFormat; private final MediaCodec mediaCodec; @Nullable private final Surface inputSurface; - private final boolean decoderNeedsFrameDroppingWorkaround; - private final boolean requestedHdrToneMapping; + private final int maxPendingFrameCount; private @MonotonicNonNull Format outputFormat; @Nullable private ByteBuffer outputBuffer; @@ -105,6 +104,7 @@ public final class DefaultCodec implements Codec { boolean isVideo = MimeTypes.isVideo(checkNotNull(configurationFormat.sampleMimeType)); @Nullable MediaCodec mediaCodec = null; @Nullable Surface inputSurface = null; + boolean requestedHdrToneMapping; try { requestedHdrToneMapping = SDK_INT >= 29 && Api29.isSdrToneMappingEnabled(configurationMediaFormat); @@ -135,7 +135,8 @@ public final class DefaultCodec implements Codec { } this.mediaCodec = mediaCodec; this.inputSurface = inputSurface; - decoderNeedsFrameDroppingWorkaround = decoderNeedsFrameDroppingWorkaround(context); + maxPendingFrameCount = + getMaxPendingFrameCountInternal(context, mediaCodecName, requestedHdrToneMapping); } @Override @@ -150,32 +151,7 @@ public final class DefaultCodec implements Codec { @Override public int getMaxPendingFrameCount() { - if (decoderNeedsFrameDroppingWorkaround) { - // Allow a maximum of one frame to be pending at a time to prevent frame dropping. - // TODO(b/226330223): Investigate increasing this limit. - return 1; - } - if (Ascii.toUpperCase(getName()).startsWith("OMX.")) { - // Some OMX decoders don't correctly track their number of output buffers available, and get - // stuck if too many frames are rendered without being processed, so limit the number of - // pending frames to avoid getting stuck. This value is experimentally determined. See also - // b/213455700, b/230097284, b/229978305, and b/245491744. - // - // OMX video codecs should no longer exist from android.os.Build.DEVICE_INITIAL_SDK_INT 31+. - return 5; - } - if (requestedHdrToneMapping - && getName().equals("c2.qti.hevc.decoder") - && MODEL.equals("SM-F936B")) { - // This decoder gets stuck if too many frames are rendered without being processed when - // tone-mapping HDR10. This value is experimentally determined. See also b/260408846. - // TODO(b/260713009): Add API version check after bug is fixed on new API versions. - return 12; - } - - // Otherwise don't limit the number of frames that can be pending at a time, to maximize - // throughput. - return UNLIMITED_PENDING_FRAME_COUNT; + return maxPendingFrameCount; } @Override @@ -488,13 +464,40 @@ public final class DefaultCodec implements Codec { TraceUtil.endSection(); } - private static boolean decoderNeedsFrameDroppingWorkaround(Context context) { - // Prior to API 29, decoders may drop frames to keep their output surface from growing out of - // bounds. From API 29, if the app targets API 29 or later, the {@link - // MediaFormat#KEY_ALLOW_FRAME_DROP} key prevents frame dropping even when the surface is full. - // Frame dropping is never desired, so a workaround is needed for older API levels. - return SDK_INT < 29 - || context.getApplicationContext().getApplicationInfo().targetSdkVersion < 29; + private static int getMaxPendingFrameCountInternal( + Context context, String codecName, boolean requestedHdrToneMapping) { + if (SDK_INT < 29 + || context.getApplicationContext().getApplicationInfo().targetSdkVersion < 29) { + // Prior to API 29, decoders may drop frames to keep their output surface from growing out of + // bounds. From API 29, if the app targets API 29 or later, the {@link + // MediaFormat#KEY_ALLOW_FRAME_DROP} key prevents frame dropping even when the surface is + // full. + // Frame dropping is never desired, so a workaround is needed for older API levels. + // Allow a maximum of one frame to be pending at a time to prevent frame dropping. + // TODO(b/226330223): Investigate increasing this limit. + return 1; + } + if (Ascii.toUpperCase(codecName).startsWith("OMX.")) { + // Some OMX decoders don't correctly track their number of output buffers available, and get + // stuck if too many frames are rendered without being processed, so limit the number of + // pending frames to avoid getting stuck. This value is experimentally determined. See also + // b/213455700, b/230097284, b/229978305, and b/245491744. + // + // OMX video codecs should no longer exist from android.os.Build.DEVICE_INITIAL_SDK_INT 31+. + return 5; + } + if (requestedHdrToneMapping + && codecName.equals("c2.qti.hevc.decoder") + && MODEL.equals("SM-F936B")) { + // This decoder gets stuck if too many frames are rendered without being processed when + // tone-mapping HDR10. This value is experimentally determined. See also b/260408846. + // TODO(b/260713009): Add API version check after bug is fixed on new API versions. + return 12; + } + + // Otherwise don't limit the number of frames that can be pending at a time, to maximize + // throughput. + return UNLIMITED_PENDING_FRAME_COUNT; } @RequiresApi(29) From 5f73984823b943d750f41519d431ad3b12dada65 Mon Sep 17 00:00:00 2001 From: rohks Date: Wed, 30 Nov 2022 21:29:53 +0000 Subject: [PATCH 032/183] Parse and set bitrates in `Ac3Reader` PiperOrigin-RevId: 492003800 --- .../android/exoplayer2/audio/Ac3Util.java | 21 +++++++++++++++++-- .../exoplayer2/extractor/ts/Ac3Reader.java | 10 +++++++-- .../extractordumps/ts/sample.ac3.0.dump | 2 ++ .../ts/sample.ac3.unknown_length.dump | 2 ++ .../extractordumps/ts/sample.eac3.0.dump | 1 + .../ts/sample.eac3.unknown_length.dump | 1 + .../extractordumps/ts/sample_ac3.ps.0.dump | 2 ++ .../ts/sample_ac3.ps.unknown_length.dump | 2 ++ .../extractordumps/ts/sample_ac3.ts.0.dump | 2 ++ .../extractordumps/ts/sample_ac3.ts.1.dump | 2 ++ .../extractordumps/ts/sample_ac3.ts.2.dump | 2 ++ .../extractordumps/ts/sample_ac3.ts.3.dump | 2 ++ .../ts/sample_ac3.ts.unknown_length.dump | 2 ++ .../extractordumps/ts/sample_ait.ts.0.dump | 1 + .../ts/sample_ait.ts.unknown_length.dump | 1 + .../extractordumps/ts/sample_eac3.ts.0.dump | 1 + .../extractordumps/ts/sample_eac3.ts.1.dump | 1 + .../extractordumps/ts/sample_eac3.ts.2.dump | 1 + .../extractordumps/ts/sample_eac3.ts.3.dump | 1 + .../ts/sample_eac3.ts.unknown_length.dump | 1 + .../ts/sample_eac3joc.ec3.0.dump | 1 + .../ts/sample_eac3joc.ec3.unknown_length.dump | 1 + .../ts/sample_eac3joc.ts.0.dump | 1 + .../ts/sample_eac3joc.ts.1.dump | 1 + .../ts/sample_eac3joc.ts.2.dump | 1 + .../ts/sample_eac3joc.ts.3.dump | 1 + .../ts/sample_eac3joc.ts.unknown_length.dump | 1 + 27 files changed, 61 insertions(+), 4 deletions(-) diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java b/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java index 07f2f710c6..4ef68bf345 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java @@ -78,6 +78,8 @@ public final class Ac3Util { public final int frameSize; /** Number of audio samples in the frame. */ public final int sampleCount; + /** The bitrate of audio samples. */ + public final int bitrate; private SyncFrameInfo( @Nullable String mimeType, @@ -85,13 +87,15 @@ public final class Ac3Util { int channelCount, int sampleRate, int frameSize, - int sampleCount) { + int sampleCount, + int bitrate) { this.mimeType = mimeType; this.streamType = streamType; this.channelCount = channelCount; this.sampleRate = sampleRate; this.frameSize = frameSize; this.sampleCount = sampleCount; + this.bitrate = bitrate; } } @@ -259,6 +263,7 @@ public final class Ac3Util { int sampleCount; boolean lfeon; int channelCount; + int bitrate; if (isEac3) { // Subsection E.1.2. data.skipBits(16); // syncword @@ -291,6 +296,7 @@ public final class Ac3Util { sampleRate = SAMPLE_RATE_BY_FSCOD[fscod]; } sampleCount = AUDIO_SAMPLES_PER_AUDIO_BLOCK * audioBlocks; + bitrate = calculateEac3Bitrate(frameSize, sampleRate, audioBlocks); acmod = data.readBits(3); lfeon = data.readBit(); channelCount = CHANNEL_COUNT_BY_ACMOD[acmod] + (lfeon ? 1 : 0); @@ -446,6 +452,7 @@ public final class Ac3Util { mimeType = null; } int frmsizecod = data.readBits(6); + bitrate = BITRATE_BY_HALF_FRMSIZECOD[frmsizecod / 2] * 1000; frameSize = getAc3SyncframeSize(fscod, frmsizecod); data.skipBits(5 + 3); // bsid, bsmod acmod = data.readBits(3); @@ -465,7 +472,7 @@ public final class Ac3Util { channelCount = CHANNEL_COUNT_BY_ACMOD[acmod] + (lfeon ? 1 : 0); } return new SyncFrameInfo( - mimeType, streamType, channelCount, sampleRate, frameSize, sampleCount); + mimeType, streamType, channelCount, sampleRate, frameSize, sampleCount, bitrate); } /** @@ -587,5 +594,15 @@ public final class Ac3Util { } } + /** + * Derived from the formula defined in F.6.2.2 to calculate data_rate for the (E-)AC3 bitstream. + * Note: The formula is based on frmsiz read from the spec. We already do some modifications to it + * when deriving frameSize from the read value. The formula used here is adapted to accommodate + * that modification. + */ + private static int calculateEac3Bitrate(int frameSize, int sampleRate, int audioBlocks) { + return (frameSize * sampleRate) / (audioBlocks * 32); + } + private Ac3Util() {} } 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 2b7d0a1d75..01b86edae8 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 @@ -28,6 +28,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.ParsableBitArray; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; @@ -207,14 +208,19 @@ public final class Ac3Reader implements ElementaryStreamReader { || frameInfo.channelCount != format.channelCount || frameInfo.sampleRate != format.sampleRate || !Util.areEqual(frameInfo.mimeType, format.sampleMimeType)) { - format = + Format.Builder formatBuilder = new Format.Builder() .setId(formatId) .setSampleMimeType(frameInfo.mimeType) .setChannelCount(frameInfo.channelCount) .setSampleRate(frameInfo.sampleRate) .setLanguage(language) - .build(); + .setPeakBitrate(frameInfo.bitrate); + // AC3 has constant bitrate, so averageBitrate = peakBitrate + if (MimeTypes.AUDIO_AC3.equals(frameInfo.mimeType)) { + formatBuilder.setAverageBitrate(frameInfo.bitrate); + } + format = formatBuilder.build(); output.format(format); } sampleSize = frameInfo.frameSize; diff --git a/testdata/src/test/assets/extractordumps/ts/sample.ac3.0.dump b/testdata/src/test/assets/extractordumps/ts/sample.ac3.0.dump index 3f582caedd..8aad7940f2 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample.ac3.0.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample.ac3.0.dump @@ -7,6 +7,8 @@ track 0: total output bytes = 13281 sample count = 8 format 0: + averageBitrate = 384000 + peakBitrate = 384000 id = 0 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample.ac3.unknown_length.dump b/testdata/src/test/assets/extractordumps/ts/sample.ac3.unknown_length.dump index 3f582caedd..8aad7940f2 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample.ac3.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample.ac3.unknown_length.dump @@ -7,6 +7,8 @@ track 0: total output bytes = 13281 sample count = 8 format 0: + averageBitrate = 384000 + peakBitrate = 384000 id = 0 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample.eac3.0.dump b/testdata/src/test/assets/extractordumps/ts/sample.eac3.0.dump index f3d9d3997d..f8be0e618c 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample.eac3.0.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample.eac3.0.dump @@ -7,6 +7,7 @@ track 0: total output bytes = 216000 sample count = 54 format 0: + peakBitrate = 6000000 id = 0 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample.eac3.unknown_length.dump b/testdata/src/test/assets/extractordumps/ts/sample.eac3.unknown_length.dump index f3d9d3997d..f8be0e618c 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample.eac3.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample.eac3.unknown_length.dump @@ -7,6 +7,7 @@ track 0: total output bytes = 216000 sample count = 54 format 0: + peakBitrate = 6000000 id = 0 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ps.0.dump b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ps.0.dump index 27d0c450fd..143245058f 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ps.0.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ps.0.dump @@ -10,6 +10,8 @@ track 189: total output bytes = 1252 sample count = 3 format 0: + averageBitrate = 96000 + peakBitrate = 96000 id = 189 sampleMimeType = audio/ac3 channelCount = 1 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ps.unknown_length.dump b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ps.unknown_length.dump index 960882156b..62c215256f 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ps.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ps.unknown_length.dump @@ -7,6 +7,8 @@ track 189: total output bytes = 1252 sample count = 3 format 0: + averageBitrate = 96000 + peakBitrate = 96000 id = 189 sampleMimeType = audio/ac3 channelCount = 1 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.0.dump b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.0.dump index 561963e10c..f3ac4e2018 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.0.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.0.dump @@ -10,6 +10,8 @@ track 1900: total output bytes = 13281 sample count = 8 format 0: + averageBitrate = 384000 + peakBitrate = 384000 id = 1/1900 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.1.dump index d778af898d..9f141492b2 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.1.dump @@ -10,6 +10,8 @@ track 1900: total output bytes = 10209 sample count = 6 format 0: + averageBitrate = 384000 + peakBitrate = 384000 id = 1/1900 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.2.dump b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.2.dump index f48ba43854..e6cea3993f 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.2.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.2.dump @@ -10,6 +10,8 @@ track 1900: total output bytes = 7137 sample count = 4 format 0: + averageBitrate = 384000 + peakBitrate = 384000 id = 1/1900 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.3.dump b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.3.dump index 997d7a6b02..da9814ead3 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.3.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.3.dump @@ -10,6 +10,8 @@ track 1900: total output bytes = 0 sample count = 0 format 0: + averageBitrate = 384000 + peakBitrate = 384000 id = 1/1900 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.unknown_length.dump b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.unknown_length.dump index a98cb798cb..f992ac64e8 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_ac3.ts.unknown_length.dump @@ -7,6 +7,8 @@ track 1900: total output bytes = 13281 sample count = 8 format 0: + averageBitrate = 384000 + peakBitrate = 384000 id = 1/1900 sampleMimeType = audio/ac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_ait.ts.0.dump b/testdata/src/test/assets/extractordumps/ts/sample_ait.ts.0.dump index 355b403293..3a305ed662 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_ait.ts.0.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_ait.ts.0.dump @@ -7,6 +7,7 @@ track 330: total output bytes = 9928 sample count = 19 format 0: + peakBitrate = 128000 id = 1031/330 sampleMimeType = audio/eac3 channelCount = 2 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_ait.ts.unknown_length.dump b/testdata/src/test/assets/extractordumps/ts/sample_ait.ts.unknown_length.dump index 355b403293..3a305ed662 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_ait.ts.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_ait.ts.unknown_length.dump @@ -7,6 +7,7 @@ track 330: total output bytes = 9928 sample count = 19 format 0: + peakBitrate = 128000 id = 1031/330 sampleMimeType = audio/eac3 channelCount = 2 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.0.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.0.dump index dfc89c5f19..2ccaceef7f 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.0.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.0.dump @@ -10,6 +10,7 @@ track 1900: total output bytes = 216000 sample count = 54 format 0: + peakBitrate = 6000000 id = 1/1900 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.1.dump index c06294df2c..ccf162fc31 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.1.dump @@ -10,6 +10,7 @@ track 1900: total output bytes = 168000 sample count = 42 format 0: + peakBitrate = 6000000 id = 1/1900 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.2.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.2.dump index 9104607498..286fc25b16 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.2.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.2.dump @@ -10,6 +10,7 @@ track 1900: total output bytes = 96000 sample count = 24 format 0: + peakBitrate = 6000000 id = 1/1900 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.3.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.3.dump index c490b7eca8..cfbfae20b6 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.3.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.3.dump @@ -10,6 +10,7 @@ track 1900: total output bytes = 0 sample count = 0 format 0: + peakBitrate = 6000000 id = 1/1900 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.unknown_length.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.unknown_length.dump index 0aae4097a7..4bb8650d72 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3.ts.unknown_length.dump @@ -7,6 +7,7 @@ track 1900: total output bytes = 216000 sample count = 54 format 0: + peakBitrate = 6000000 id = 1/1900 sampleMimeType = audio/eac3 channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ec3.0.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ec3.0.dump index f8888698bd..5a8f918105 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ec3.0.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ec3.0.dump @@ -7,6 +7,7 @@ track 0: total output bytes = 163840 sample count = 64 format 0: + peakBitrate = 640000 id = 0 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ec3.unknown_length.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ec3.unknown_length.dump index f8888698bd..5a8f918105 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ec3.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ec3.unknown_length.dump @@ -7,6 +7,7 @@ track 0: total output bytes = 163840 sample count = 64 format 0: + peakBitrate = 640000 id = 0 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.0.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.0.dump index a3cf812691..2fc2f49280 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.0.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.0.dump @@ -10,6 +10,7 @@ track 1900: total output bytes = 163840 sample count = 64 format 0: + peakBitrate = 640000 id = 1/1900 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.1.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.1.dump index 77951bd767..771c5216c5 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.1.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.1.dump @@ -10,6 +10,7 @@ track 1900: total output bytes = 112640 sample count = 44 format 0: + peakBitrate = 640000 id = 1/1900 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.2.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.2.dump index 0354754df2..452d8eea13 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.2.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.2.dump @@ -10,6 +10,7 @@ track 1900: total output bytes = 56320 sample count = 22 format 0: + peakBitrate = 640000 id = 1/1900 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.3.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.3.dump index 742d87e271..8da152a79f 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.3.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.3.dump @@ -10,6 +10,7 @@ track 1900: total output bytes = 5120 sample count = 2 format 0: + peakBitrate = 640000 id = 1/1900 sampleMimeType = audio/eac3-joc channelCount = 6 diff --git a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.unknown_length.dump b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.unknown_length.dump index 269dd63593..82ce1d24bb 100644 --- a/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.unknown_length.dump +++ b/testdata/src/test/assets/extractordumps/ts/sample_eac3joc.ts.unknown_length.dump @@ -7,6 +7,7 @@ track 1900: total output bytes = 163840 sample count = 64 format 0: + peakBitrate = 640000 id = 1/1900 sampleMimeType = audio/eac3-joc channelCount = 6 From e4db710deb8fd08b2a47f9d1c33c31892b3b8433 Mon Sep 17 00:00:00 2001 From: claincly Date: Wed, 30 Nov 2022 22:46:25 +0000 Subject: [PATCH 033/183] Fix Samsung MediaCodec encoder reports incorrect timestmp in EOS PiperOrigin-RevId: 492023573 --- .../VideoTranscodingSamplePipeline.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java index a6937b9193..40d3aa804a 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java @@ -64,6 +64,12 @@ import org.checkerframework.dataflow.qual.Pure; private final EncoderWrapper encoderWrapper; private final DecoderInputBuffer encoderOutputBuffer; + /** + * The timestamp of the last buffer processed before {@linkplain + * FrameProcessor.Listener#onFrameProcessingEnded() frame processing has ended}. + */ + private volatile long finalFramePresentationTimeUs; + public VideoTranscodingSamplePipeline( Context context, Format inputFormat, @@ -109,6 +115,8 @@ import org.checkerframework.dataflow.qual.Pure; /* mediaCodecName= */ null, TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED); } + + finalFramePresentationTimeUs = C.TIME_UNSET; } decoderInputBuffer = @@ -151,6 +159,8 @@ import org.checkerframework.dataflow.qual.Pure; frameProcessorFactory.create( context, new FrameProcessor.Listener() { + private long lastProcessedFramePresentationTimeUs; + @Override public void onOutputSizeChanged(int width, int height) { try { @@ -163,7 +173,8 @@ import org.checkerframework.dataflow.qual.Pure; @Override public void onOutputFrameAvailable(long presentationTimeUs) { - // Do nothing as frames are released automatically. + // Frames are released automatically. + lastProcessedFramePresentationTimeUs = presentationTimeUs; } @Override @@ -175,6 +186,8 @@ import org.checkerframework.dataflow.qual.Pure; @Override public void onFrameProcessingEnded() { + VideoTranscodingSamplePipeline.this.finalFramePresentationTimeUs = + lastProcessedFramePresentationTimeUs; try { encoderWrapper.signalEndOfInputStream(); } catch (TransformationException exception) { @@ -264,6 +277,16 @@ import org.checkerframework.dataflow.qual.Pure; return null; } MediaCodec.BufferInfo bufferInfo = checkNotNull(encoderWrapper.getOutputBufferInfo()); + if (finalFramePresentationTimeUs != C.TIME_UNSET + && bufferInfo.size > 0 + && bufferInfo.presentationTimeUs == 0) { + // Internal ref b/235045165: Some encoder incorrectly set a zero presentation time on the + // penultimate buffer (before EOS), and sets the actual timestamp on the EOS buffer. Use the + // last processed frame presentation time instead. + // bufferInfo.presentationTimeUs should never be 0 because we apply streamOffsetUs to the + // buffer presentationTimeUs. + bufferInfo.presentationTimeUs = finalFramePresentationTimeUs; + } encoderOutputBuffer.timeUs = bufferInfo.presentationTimeUs; encoderOutputBuffer.setFlags(bufferInfo.flags); return encoderOutputBuffer; From 1ac72de551a07d37c3b80d96028463244407a5b4 Mon Sep 17 00:00:00 2001 From: tonihei Date: Thu, 1 Dec 2022 08:30:19 +0000 Subject: [PATCH 034/183] Add media type to MediaMetadata This helps to denote what type of content or folder the metadata describes. PiperOrigin-RevId: 492123690 --- .../android/exoplayer2/MediaMetadata.java | 215 +++++++++++++++++- .../android/exoplayer2/MediaMetadataTest.java | 2 + 2 files changed, 214 insertions(+), 3 deletions(-) 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 da59d7c09e..77bbcb9de8 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 @@ -76,6 +76,7 @@ public final class MediaMetadata implements Bundleable { @Nullable private CharSequence genre; @Nullable private CharSequence compilation; @Nullable private CharSequence station; + @Nullable private @MediaType Integer mediaType; @Nullable private Bundle extras; public Builder() {} @@ -111,6 +112,7 @@ public final class MediaMetadata implements Bundleable { this.genre = mediaMetadata.genre; this.compilation = mediaMetadata.compilation; this.station = mediaMetadata.station; + this.mediaType = mediaMetadata.mediaType; this.extras = mediaMetadata.extras; } @@ -381,6 +383,13 @@ public final class MediaMetadata implements Bundleable { return this; } + /** Sets the {@link MediaType}. */ + @CanIgnoreReturnValue + public Builder setMediaType(@Nullable @MediaType Integer mediaType) { + this.mediaType = mediaType; + return this; + } + /** Sets the extras {@link Bundle}. */ @CanIgnoreReturnValue public Builder setExtras(@Nullable Bundle extras) { @@ -524,6 +533,9 @@ public final class MediaMetadata implements Bundleable { if (mediaMetadata.station != null) { setStation(mediaMetadata.station); } + if (mediaMetadata.mediaType != null) { + setMediaType(mediaMetadata.mediaType); + } if (mediaMetadata.extras != null) { setExtras(mediaMetadata.extras); } @@ -537,12 +549,185 @@ public final class MediaMetadata implements Bundleable { } } + /** + * The type of content described by the media item. + * + *

One of {@link #MEDIA_TYPE_MIXED}, {@link #MEDIA_TYPE_MUSIC}, {@link + * #MEDIA_TYPE_AUDIO_BOOK_CHAPTER}, {@link #MEDIA_TYPE_PODCAST_EPISODE}, {@link + * #MEDIA_TYPE_RADIO_STATION}, {@link #MEDIA_TYPE_NEWS}, {@link #MEDIA_TYPE_VIDEO}, {@link + * #MEDIA_TYPE_TRAILER}, {@link #MEDIA_TYPE_MOVIE}, {@link #MEDIA_TYPE_TV_SHOW}, {@link + * #MEDIA_TYPE_ALBUM}, {@link #MEDIA_TYPE_ARTIST}, {@link #MEDIA_TYPE_GENRE}, {@link + * #MEDIA_TYPE_PLAYLIST}, {@link #MEDIA_TYPE_YEAR}, {@link #MEDIA_TYPE_AUDIO_BOOK}, {@link + * #MEDIA_TYPE_PODCAST}, {@link #MEDIA_TYPE_TV_CHANNEL}, {@link #MEDIA_TYPE_TV_SERIES}, {@link + * #MEDIA_TYPE_TV_SEASON}, {@link #MEDIA_TYPE_FOLDER_MIXED}, {@link #MEDIA_TYPE_FOLDER_ALBUMS}, + * {@link #MEDIA_TYPE_FOLDER_ARTISTS}, {@link #MEDIA_TYPE_FOLDER_GENRES}, {@link + * #MEDIA_TYPE_FOLDER_PLAYLISTS}, {@link #MEDIA_TYPE_FOLDER_YEARS}, {@link + * #MEDIA_TYPE_FOLDER_AUDIO_BOOKS}, {@link #MEDIA_TYPE_FOLDER_PODCASTS}, {@link + * #MEDIA_TYPE_FOLDER_TV_CHANNELS}, {@link #MEDIA_TYPE_FOLDER_TV_SERIES}, {@link + * #MEDIA_TYPE_FOLDER_TV_SHOWS}, {@link #MEDIA_TYPE_FOLDER_RADIO_STATIONS}, {@link + * #MEDIA_TYPE_FOLDER_NEWS}, {@link #MEDIA_TYPE_FOLDER_VIDEOS}, {@link + * #MEDIA_TYPE_FOLDER_TRAILERS} or {@link #MEDIA_TYPE_FOLDER_MOVIES}. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @Target(TYPE_USE) + @IntDef({ + MEDIA_TYPE_MIXED, + MEDIA_TYPE_MUSIC, + MEDIA_TYPE_AUDIO_BOOK_CHAPTER, + MEDIA_TYPE_PODCAST_EPISODE, + MEDIA_TYPE_RADIO_STATION, + MEDIA_TYPE_NEWS, + MEDIA_TYPE_VIDEO, + MEDIA_TYPE_TRAILER, + MEDIA_TYPE_MOVIE, + MEDIA_TYPE_TV_SHOW, + MEDIA_TYPE_ALBUM, + MEDIA_TYPE_ARTIST, + MEDIA_TYPE_GENRE, + MEDIA_TYPE_PLAYLIST, + MEDIA_TYPE_YEAR, + MEDIA_TYPE_AUDIO_BOOK, + MEDIA_TYPE_PODCAST, + MEDIA_TYPE_TV_CHANNEL, + MEDIA_TYPE_TV_SERIES, + MEDIA_TYPE_TV_SEASON, + MEDIA_TYPE_FOLDER_MIXED, + MEDIA_TYPE_FOLDER_ALBUMS, + MEDIA_TYPE_FOLDER_ARTISTS, + MEDIA_TYPE_FOLDER_GENRES, + MEDIA_TYPE_FOLDER_PLAYLISTS, + MEDIA_TYPE_FOLDER_YEARS, + MEDIA_TYPE_FOLDER_AUDIO_BOOKS, + MEDIA_TYPE_FOLDER_PODCASTS, + MEDIA_TYPE_FOLDER_TV_CHANNELS, + MEDIA_TYPE_FOLDER_TV_SERIES, + MEDIA_TYPE_FOLDER_TV_SHOWS, + MEDIA_TYPE_FOLDER_RADIO_STATIONS, + MEDIA_TYPE_FOLDER_NEWS, + MEDIA_TYPE_FOLDER_VIDEOS, + MEDIA_TYPE_FOLDER_TRAILERS, + MEDIA_TYPE_FOLDER_MOVIES, + }) + public @interface MediaType {} + + /** Media of undetermined type or a mix of multiple {@linkplain MediaType media types}. */ + public static final int MEDIA_TYPE_MIXED = 0; + /** {@link MediaType} for music. */ + public static final int MEDIA_TYPE_MUSIC = 1; + /** {@link MediaType} for an audio book chapter. */ + public static final int MEDIA_TYPE_AUDIO_BOOK_CHAPTER = 2; + /** {@link MediaType} for a podcast episode. */ + public static final int MEDIA_TYPE_PODCAST_EPISODE = 3; + /** {@link MediaType} for a radio station. */ + public static final int MEDIA_TYPE_RADIO_STATION = 4; + /** {@link MediaType} for news. */ + public static final int MEDIA_TYPE_NEWS = 5; + /** {@link MediaType} for a video. */ + public static final int MEDIA_TYPE_VIDEO = 6; + /** {@link MediaType} for a movie trailer. */ + public static final int MEDIA_TYPE_TRAILER = 7; + /** {@link MediaType} for a movie. */ + public static final int MEDIA_TYPE_MOVIE = 8; + /** {@link MediaType} for a TV show. */ + public static final int MEDIA_TYPE_TV_SHOW = 9; + /** + * {@link MediaType} for a group of items (e.g., {@link #MEDIA_TYPE_MUSIC music}) belonging to an + * album. + */ + public static final int MEDIA_TYPE_ALBUM = 10; + /** + * {@link MediaType} for a group of items (e.g., {@link #MEDIA_TYPE_MUSIC music}) from the same + * artist. + */ + public static final int MEDIA_TYPE_ARTIST = 11; + /** + * {@link MediaType} for a group of items (e.g., {@link #MEDIA_TYPE_MUSIC music}) of the same + * genre. + */ + public static final int MEDIA_TYPE_GENRE = 12; + /** + * {@link MediaType} for a group of items (e.g., {@link #MEDIA_TYPE_MUSIC music}) forming a + * playlist. + */ + public static final int MEDIA_TYPE_PLAYLIST = 13; + /** + * {@link MediaType} for a group of items (e.g., {@link #MEDIA_TYPE_MUSIC music}) from the same + * year. + */ + public static final int MEDIA_TYPE_YEAR = 14; + /** + * {@link MediaType} for a group of items forming an audio book. Items in this group are typically + * of type {@link #MEDIA_TYPE_AUDIO_BOOK_CHAPTER}. + */ + public static final int MEDIA_TYPE_AUDIO_BOOK = 15; + /** + * {@link MediaType} for a group of items belonging to a podcast. Items in this group are + * typically of type {@link #MEDIA_TYPE_PODCAST_EPISODE}. + */ + public static final int MEDIA_TYPE_PODCAST = 16; + /** + * {@link MediaType} for a group of items that are part of a TV channel. Items in this group are + * typically of type {@link #MEDIA_TYPE_TV_SHOW}, {@link #MEDIA_TYPE_TV_SERIES} or {@link + * #MEDIA_TYPE_MOVIE}. + */ + public static final int MEDIA_TYPE_TV_CHANNEL = 17; + /** + * {@link MediaType} for a group of items that are part of a TV series. Items in this group are + * typically of type {@link #MEDIA_TYPE_TV_SHOW} or {@link #MEDIA_TYPE_TV_SEASON}. + */ + public static final int MEDIA_TYPE_TV_SERIES = 18; + /** + * {@link MediaType} for a group of items that are part of a TV series. Items in this group are + * typically of type {@link #MEDIA_TYPE_TV_SHOW}. + */ + public static final int MEDIA_TYPE_TV_SEASON = 19; + /** {@link MediaType} for a folder with mixed or undetermined content. */ + public static final int MEDIA_TYPE_FOLDER_MIXED = 20; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_ALBUM albums}. */ + public static final int MEDIA_TYPE_FOLDER_ALBUMS = 21; + /** {@link MediaType} for a folder containing {@linkplain #FIELD_ARTIST artists}. */ + public static final int MEDIA_TYPE_FOLDER_ARTISTS = 22; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_GENRE genres}. */ + public static final int MEDIA_TYPE_FOLDER_GENRES = 23; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_PLAYLIST playlists}. */ + public static final int MEDIA_TYPE_FOLDER_PLAYLISTS = 24; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_YEAR years}. */ + public static final int MEDIA_TYPE_FOLDER_YEARS = 25; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_AUDIO_BOOK audio books}. */ + public static final int MEDIA_TYPE_FOLDER_AUDIO_BOOKS = 26; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_PODCAST podcasts}. */ + public static final int MEDIA_TYPE_FOLDER_PODCASTS = 27; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_TV_CHANNEL TV channels}. */ + public static final int MEDIA_TYPE_FOLDER_TV_CHANNELS = 28; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_TV_SERIES TV series}. */ + public static final int MEDIA_TYPE_FOLDER_TV_SERIES = 29; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_TV_SHOW TV shows}. */ + public static final int MEDIA_TYPE_FOLDER_TV_SHOWS = 30; + /** + * {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_RADIO_STATION radio + * stations}. + */ + public static final int MEDIA_TYPE_FOLDER_RADIO_STATIONS = 31; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_NEWS news}. */ + public static final int MEDIA_TYPE_FOLDER_NEWS = 32; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_VIDEO videos}. */ + public static final int MEDIA_TYPE_FOLDER_VIDEOS = 33; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_TRAILER movie trailers}. */ + public static final int MEDIA_TYPE_FOLDER_TRAILERS = 34; + /** {@link MediaType} for a folder containing {@linkplain #MEDIA_TYPE_MOVIE movies}. */ + public static final int MEDIA_TYPE_FOLDER_MOVIES = 35; + /** * The folder type of the media item. * *

This can be used as the type of a browsable bluetooth folder (see section 6.10.2.2 of the Bluetooth * AVRCP 1.6.2). + * + *

One of {@link #FOLDER_TYPE_NONE}, {@link #FOLDER_TYPE_MIXED}, {@link #FOLDER_TYPE_TITLES}, + * {@link #FOLDER_TYPE_ALBUMS}, {@link #FOLDER_TYPE_ARTISTS}, {@link #FOLDER_TYPE_GENRES}, {@link + * #FOLDER_TYPE_PLAYLISTS} or {@link #FOLDER_TYPE_YEARS}. */ // @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility // with Kotlin usages from before TYPE_USE was added. @@ -583,6 +768,17 @@ public final class MediaMetadata implements Bundleable { * *

Values sourced from the ID3 v2.4 specification (See section 4.14 of * https://id3.org/id3v2.4.0-frames). + * + *

One of {@link #PICTURE_TYPE_OTHER}, {@link #PICTURE_TYPE_FILE_ICON}, {@link + * #PICTURE_TYPE_FILE_ICON_OTHER}, {@link #PICTURE_TYPE_FRONT_COVER}, {@link + * #PICTURE_TYPE_BACK_COVER}, {@link #PICTURE_TYPE_LEAFLET_PAGE}, {@link #PICTURE_TYPE_MEDIA}, + * {@link #PICTURE_TYPE_LEAD_ARTIST_PERFORMER}, {@link #PICTURE_TYPE_ARTIST_PERFORMER}, {@link + * #PICTURE_TYPE_CONDUCTOR}, {@link #PICTURE_TYPE_BAND_ORCHESTRA}, {@link #PICTURE_TYPE_COMPOSER}, + * {@link #PICTURE_TYPE_LYRICIST}, {@link #PICTURE_TYPE_RECORDING_LOCATION}, {@link + * #PICTURE_TYPE_DURING_RECORDING}, {@link #PICTURE_TYPE_DURING_PERFORMANCE}, {@link + * #PICTURE_TYPE_MOVIE_VIDEO_SCREEN_CAPTURE}, {@link #PICTURE_TYPE_A_BRIGHT_COLORED_FISH}, {@link + * #PICTURE_TYPE_ILLUSTRATION}, {@link #PICTURE_TYPE_BAND_ARTIST_LOGO} or {@link + * #PICTURE_TYPE_PUBLISHER_STUDIO_LOGO}. */ // @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility // with Kotlin usages from before TYPE_USE was added. @@ -724,6 +920,8 @@ public final class MediaMetadata implements Bundleable { @Nullable public final CharSequence compilation; /** Optional name of the station streaming the media. */ @Nullable public final CharSequence station; + /** Optional {@link MediaType}. */ + @Nullable public final @MediaType Integer mediaType; /** * Optional extras {@link Bundle}. @@ -765,6 +963,7 @@ public final class MediaMetadata implements Bundleable { this.genre = builder.genre; this.compilation = builder.compilation; this.station = builder.station; + this.mediaType = builder.mediaType; this.extras = builder.extras; } @@ -811,7 +1010,8 @@ public final class MediaMetadata implements Bundleable { && Util.areEqual(totalDiscCount, that.totalDiscCount) && Util.areEqual(genre, that.genre) && Util.areEqual(compilation, that.compilation) - && Util.areEqual(station, that.station); + && Util.areEqual(station, that.station) + && Util.areEqual(mediaType, that.mediaType); } @Override @@ -846,7 +1046,8 @@ public final class MediaMetadata implements Bundleable { totalDiscCount, genre, compilation, - station); + station, + mediaType); } // Bundleable implementation. @@ -886,7 +1087,8 @@ public final class MediaMetadata implements Bundleable { FIELD_GENRE, FIELD_COMPILATION, FIELD_STATION, - FIELD_EXTRAS + FIELD_MEDIA_TYPE, + FIELD_EXTRAS, }) private @interface FieldNumber {} @@ -921,6 +1123,7 @@ public final class MediaMetadata implements Bundleable { private static final int FIELD_COMPILATION = 28; private static final int FIELD_ARTWORK_DATA_TYPE = 29; private static final int FIELD_STATION = 30; + private static final int FIELD_MEDIA_TYPE = 31; private static final int FIELD_EXTRAS = 1000; @Override @@ -987,6 +1190,9 @@ public final class MediaMetadata implements Bundleable { if (artworkDataType != null) { bundle.putInt(keyForField(FIELD_ARTWORK_DATA_TYPE), artworkDataType); } + if (mediaType != null) { + bundle.putInt(keyForField(FIELD_MEDIA_TYPE), mediaType); + } if (extras != null) { bundle.putBundle(keyForField(FIELD_EXTRAS), extras); } @@ -1068,6 +1274,9 @@ public final class MediaMetadata implements Bundleable { if (bundle.containsKey(keyForField(FIELD_TOTAL_DISC_COUNT))) { builder.setTotalDiscCount(bundle.getInt(keyForField(FIELD_TOTAL_DISC_COUNT))); } + if (bundle.containsKey(keyForField(FIELD_MEDIA_TYPE))) { + builder.setMediaType(bundle.getInt(keyForField(FIELD_MEDIA_TYPE))); + } return builder.build(); } 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 5bf5feaa62..2c1df81e40 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 @@ -64,6 +64,7 @@ public class MediaMetadataTest { assertThat(mediaMetadata.genre).isNull(); assertThat(mediaMetadata.compilation).isNull(); assertThat(mediaMetadata.station).isNull(); + assertThat(mediaMetadata.mediaType).isNull(); assertThat(mediaMetadata.extras).isNull(); } @@ -149,6 +150,7 @@ public class MediaMetadataTest { .setGenre("Pop") .setCompilation("Amazing songs.") .setStation("radio station") + .setMediaType(MediaMetadata.MEDIA_TYPE_MIXED) .setExtras(extras) .build(); } From e598a17b3628e1179fa4219ca3212407fb3fdeb1 Mon Sep 17 00:00:00 2001 From: tonihei Date: Thu, 1 Dec 2022 08:34:14 +0000 Subject: [PATCH 035/183] Add support for most setters in SimpleBasePlayer This adds the forwarding logic for most setters in SimpleExoPlayer in the same style as the existing logic for setPlayWhenReady. This change doesn't implement the setters for modifying media items, seeking and releasing yet as they require additional handling that goes beyond the repeated implementation pattern in this change. PiperOrigin-RevId: 492124399 --- .../android/exoplayer2/SimpleBasePlayer.java | 509 +++++- .../google/android/exoplayer2/util/Size.java | 3 + .../exoplayer2/SimpleBasePlayerTest.java | 1511 ++++++++++++++++- 3 files changed, 1955 insertions(+), 68 deletions(-) diff --git a/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java b/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java index 7a6e231a30..c5c9a10dc5 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java @@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import static com.google.android.exoplayer2.util.Util.usToMs; import static java.lang.Math.max; +import android.graphics.Rect; import android.os.Looper; import android.os.SystemClock; import android.util.Pair; @@ -2039,6 +2040,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void setPlayWhenReady(boolean playWhenReady) { verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. State state = this.state; if (!state.availableCommands.contains(Player.COMMAND_PLAY_PAUSE)) { return; @@ -2091,8 +2093,20 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void prepare() { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_PREPARE)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handlePrepare(), + /* placeholderStateSupplier= */ () -> + state + .buildUpon() + .setPlayerError(null) + .setPlaybackState(state.timeline.isEmpty() ? STATE_ENDED : STATE_BUFFERING) + .build()); } @Override @@ -2117,8 +2131,15 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void setRepeatMode(@Player.RepeatMode int repeatMode) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_REPEAT_MODE)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetRepeatMode(repeatMode), + /* placeholderStateSupplier= */ () -> state.buildUpon().setRepeatMode(repeatMode).build()); } @Override @@ -2130,8 +2151,16 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void setShuffleModeEnabled(boolean shuffleModeEnabled) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_SHUFFLE_MODE)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetShuffleModeEnabled(shuffleModeEnabled), + /* placeholderStateSupplier= */ () -> + state.buildUpon().setShuffleModeEnabled(shuffleModeEnabled).build()); } @Override @@ -2152,6 +2181,12 @@ public abstract class SimpleBasePlayer extends BasePlayer { throw new IllegalStateException(); } + @Override + protected final void repeatCurrentMediaItem() { + // TODO: implement. + throw new IllegalStateException(); + } + @Override public final long getSeekBackIncrement() { verifyApplicationThreadAndInitState(); @@ -2172,8 +2207,16 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void setPlaybackParameters(PlaybackParameters playbackParameters) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_SPEED_AND_PITCH)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetPlaybackParameters(playbackParameters), + /* placeholderStateSupplier= */ () -> + state.buildUpon().setPlaybackParameters(playbackParameters).build()); } @Override @@ -2184,14 +2227,30 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void stop() { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_STOP)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleStop(), + /* placeholderStateSupplier= */ () -> + state + .buildUpon() + .setPlaybackState(Player.STATE_IDLE) + .setTotalBufferedDurationMs(PositionSupplier.ZERO) + .setContentBufferedPositionMs(state.contentPositionMsSupplier) + .setAdBufferedPositionMs(state.adPositionMsSupplier) + .build()); } @Override public final void stop(boolean reset) { - // TODO: implement. - throw new IllegalStateException(); + stop(); + if (reset) { + clearMediaItems(); + } } @Override @@ -2214,8 +2273,16 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void setTrackSelectionParameters(TrackSelectionParameters parameters) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetTrackSelectionParameters(parameters), + /* placeholderStateSupplier= */ () -> + state.buildUpon().setTrackSelectionParameters(parameters).build()); } @Override @@ -2232,8 +2299,16 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void setPlaylistMetadata(MediaMetadata mediaMetadata) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_MEDIA_ITEMS_METADATA)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetPlaylistMetadata(mediaMetadata), + /* placeholderStateSupplier= */ () -> + state.buildUpon().setPlaylistMetadata(mediaMetadata).build()); } @Override @@ -2325,8 +2400,15 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void setVolume(float volume) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_VOLUME)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetVolume(volume), + /* placeholderStateSupplier= */ () -> state.buildUpon().setVolume(volume).build()); } @Override @@ -2335,58 +2417,122 @@ public abstract class SimpleBasePlayer extends BasePlayer { return state.volume; } - @Override - public final void clearVideoSurface() { - // TODO: implement. - throw new IllegalStateException(); - } - - @Override - public final void clearVideoSurface(@Nullable Surface surface) { - // TODO: implement. - throw new IllegalStateException(); - } - @Override public final void setVideoSurface(@Nullable Surface surface) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_VIDEO_SURFACE)) { + return; + } + if (surface == null) { + clearVideoSurface(); + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetVideoOutput(surface), + /* placeholderStateSupplier= */ () -> + state.buildUpon().setSurfaceSize(Size.UNKNOWN).build()); } @Override public final void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) { - // TODO: implement. - throw new IllegalStateException(); - } - - @Override - public final void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_VIDEO_SURFACE)) { + return; + } + if (surfaceHolder == null) { + clearVideoSurface(); + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetVideoOutput(surfaceHolder), + /* placeholderStateSupplier= */ () -> + state.buildUpon().setSurfaceSize(getSurfaceHolderSize(surfaceHolder)).build()); } @Override public final void setVideoSurfaceView(@Nullable SurfaceView surfaceView) { - // TODO: implement. - throw new IllegalStateException(); - } - - @Override - public final void clearVideoSurfaceView(@Nullable SurfaceView surfaceView) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_VIDEO_SURFACE)) { + return; + } + if (surfaceView == null) { + clearVideoSurface(); + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetVideoOutput(surfaceView), + /* placeholderStateSupplier= */ () -> + state + .buildUpon() + .setSurfaceSize(getSurfaceHolderSize(surfaceView.getHolder())) + .build()); } @Override public final void setVideoTextureView(@Nullable TextureView textureView) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_VIDEO_SURFACE)) { + return; + } + if (textureView == null) { + clearVideoSurface(); + return; + } + Size surfaceSize; + if (textureView.isAvailable()) { + surfaceSize = new Size(textureView.getWidth(), textureView.getHeight()); + } else { + surfaceSize = Size.ZERO; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetVideoOutput(textureView), + /* placeholderStateSupplier= */ () -> + state.buildUpon().setSurfaceSize(surfaceSize).build()); + } + + @Override + public final void clearVideoSurface() { + clearVideoOutput(/* videoOutput= */ null); + } + + @Override + public final void clearVideoSurface(@Nullable Surface surface) { + clearVideoOutput(surface); + } + + @Override + public final void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) { + clearVideoOutput(surfaceHolder); + } + + @Override + public final void clearVideoSurfaceView(@Nullable SurfaceView surfaceView) { + clearVideoOutput(surfaceView); } @Override public final void clearVideoTextureView(@Nullable TextureView textureView) { - // TODO: implement. - throw new IllegalStateException(); + clearVideoOutput(textureView); + } + + private void clearVideoOutput(@Nullable Object videoOutput) { + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_VIDEO_SURFACE)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleClearVideoOutput(videoOutput), + /* placeholderStateSupplier= */ () -> state.buildUpon().setSurfaceSize(Size.ZERO).build()); } @Override @@ -2427,26 +2573,56 @@ public abstract class SimpleBasePlayer extends BasePlayer { @Override public final void setDeviceVolume(int volume) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_SET_DEVICE_VOLUME)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetDeviceVolume(volume), + /* placeholderStateSupplier= */ () -> state.buildUpon().setDeviceVolume(volume).build()); } @Override public final void increaseDeviceVolume() { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_ADJUST_DEVICE_VOLUME)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleIncreaseDeviceVolume(), + /* placeholderStateSupplier= */ () -> + state.buildUpon().setDeviceVolume(state.deviceVolume + 1).build()); } @Override public final void decreaseDeviceVolume() { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_ADJUST_DEVICE_VOLUME)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleDecreaseDeviceVolume(), + /* placeholderStateSupplier= */ () -> + state.buildUpon().setDeviceVolume(max(0, state.deviceVolume - 1)).build()); } @Override public final void setDeviceMuted(boolean muted) { - // TODO: implement. - throw new IllegalStateException(); + verifyApplicationThreadAndInitState(); + // Use a local copy to ensure the lambda below uses the current state value. + State state = this.state; + if (!state.availableCommands.contains(Player.COMMAND_ADJUST_DEVICE_VOLUME)) { + return; + } + updateStateForPendingOperation( + /* pendingOperation= */ handleSetDeviceMuted(muted), + /* placeholderStateSupplier= */ () -> state.buildUpon().setIsDeviceMuted(muted).build()); } /** @@ -2500,22 +2676,217 @@ public abstract class SimpleBasePlayer extends BasePlayer { } /** - * Handles calls to set {@link State#playWhenReady}. + * Handles calls to {@link Player#setPlayWhenReady}, {@link Player#play} and {@link Player#pause}. * - *

Will only be called if {@link Player.Command#COMMAND_PLAY_PAUSE} is available. + *

Will only be called if {@link Player#COMMAND_PLAY_PAUSE} is available. * * @param playWhenReady The requested {@link State#playWhenReady} * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} * changes caused by this call. - * @see Player#setPlayWhenReady(boolean) - * @see Player#play() - * @see Player#pause() */ @ForOverride protected ListenableFuture handleSetPlayWhenReady(boolean playWhenReady) { throw new IllegalStateException(); } + /** + * Handles calls to {@link Player#prepare}. + * + *

Will only be called if {@link Player#COMMAND_PREPARE} is available. + * + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handlePrepare() { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#stop}. + * + *

Will only be called if {@link Player#COMMAND_STOP} is available. + * + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleStop() { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#setRepeatMode}. + * + *

Will only be called if {@link Player#COMMAND_SET_REPEAT_MODE} is available. + * + * @param repeatMode The requested {@link RepeatMode}. + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleSetRepeatMode(@RepeatMode int repeatMode) { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#setShuffleModeEnabled}. + * + *

Will only be called if {@link Player#COMMAND_SET_SHUFFLE_MODE} is available. + * + * @param shuffleModeEnabled Whether shuffle mode was requested to be enabled. + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleSetShuffleModeEnabled(boolean shuffleModeEnabled) { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#setPlaybackParameters} or {@link Player#setPlaybackSpeed}. + * + *

Will only be called if {@link Player#COMMAND_SET_SPEED_AND_PITCH} is available. + * + * @param playbackParameters The requested {@link PlaybackParameters}. + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleSetPlaybackParameters(PlaybackParameters playbackParameters) { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#setTrackSelectionParameters}. + * + *

Will only be called if {@link Player#COMMAND_SET_TRACK_SELECTION_PARAMETERS} is available. + * + * @param trackSelectionParameters The requested {@link TrackSelectionParameters}. + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleSetTrackSelectionParameters( + TrackSelectionParameters trackSelectionParameters) { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#setPlaylistMetadata}. + * + *

Will only be called if {@link Player#COMMAND_SET_MEDIA_ITEMS_METADATA} is available. + * + * @param playlistMetadata The requested {@linkplain MediaMetadata playlist metadata}. + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleSetPlaylistMetadata(MediaMetadata playlistMetadata) { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#setVolume}. + * + *

Will only be called if {@link Player#COMMAND_SET_VOLUME} is available. + * + * @param volume The requested audio volume, with 0 being silence and 1 being unity gain (signal + * unchanged). + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleSetVolume(@FloatRange(from = 0, to = 1.0) float volume) { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#setDeviceVolume}. + * + *

Will only be called if {@link Player#COMMAND_SET_DEVICE_VOLUME} is available. + * + * @param deviceVolume The requested device volume. + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleSetDeviceVolume(@IntRange(from = 0) int deviceVolume) { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#increaseDeviceVolume()}. + * + *

Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} is available. + * + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleIncreaseDeviceVolume() { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#decreaseDeviceVolume()}. + * + *

Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} is available. + * + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleDecreaseDeviceVolume() { + throw new IllegalStateException(); + } + + /** + * Handles calls to {@link Player#setDeviceMuted}. + * + *

Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} is available. + * + * @param muted Whether the device was requested to be muted. + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleSetDeviceMuted(boolean muted) { + throw new IllegalStateException(); + } + + /** + * Handles calls to set the video output. + * + *

Will only be called if {@link Player#COMMAND_SET_VIDEO_SURFACE} is available. + * + * @param videoOutput The requested video output. This is either a {@link Surface}, {@link + * SurfaceHolder}, {@link TextureView} or {@link SurfaceView}. + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleSetVideoOutput(Object videoOutput) { + throw new IllegalStateException(); + } + + /** + * Handles calls to clear the video output. + * + *

Will only be called if {@link Player#COMMAND_SET_VIDEO_SURFACE} is available. + * + * @param videoOutput The video output to clear. If null any current output should be cleared. If + * non-null, the output should only be cleared if it matches the provided argument. This is + * either a {@link Surface}, {@link SurfaceHolder}, {@link TextureView} or {@link + * SurfaceView}. + * @return A {@link ListenableFuture} indicating the completion of all immediate {@link State} + * changes caused by this call. + */ + @ForOverride + protected ListenableFuture handleClearVideoOutput(@Nullable Object videoOutput) { + throw new IllegalStateException(); + } + @SuppressWarnings("deprecation") // Calling deprecated listener methods. @RequiresNonNull("state") private void updateStateAndInformListeners(State newState) { @@ -2974,4 +3345,12 @@ public abstract class SimpleBasePlayer extends BasePlayer { } return C.INDEX_UNSET; } + + private static Size getSurfaceHolderSize(SurfaceHolder surfaceHolder) { + if (!surfaceHolder.getSurface().isValid()) { + return Size.ZERO; + } + Rect surfaceFrame = surfaceHolder.getSurfaceFrame(); + return new Size(surfaceFrame.width(), surfaceFrame.height()); + } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Size.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Size.java index c273fbf5ee..bbd8e25893 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Size.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Size.java @@ -28,6 +28,9 @@ public final class Size { public static final Size UNKNOWN = new Size(/* width= */ C.LENGTH_UNSET, /* height= */ C.LENGTH_UNSET); + /* A static instance to represent a size of zero height and width. */ + public static final Size ZERO = new Size(/* width= */ 0, /* height= */ 0); + private final int width; private final int height; diff --git a/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java b/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java index 0995639a66..ee56a1705b 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java @@ -27,8 +27,12 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import android.graphics.SurfaceTexture; import android.os.Looper; import android.os.SystemClock; +import android.view.Surface; +import androidx.annotation.Nullable; +import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.Player.Commands; import com.google.android.exoplayer2.Player.Listener; @@ -1833,17 +1837,18 @@ public class SimpleBasePlayerTest { .setPlayWhenReady( /* playWhenReady= */ true, Player.PLAY_WHEN_READY_CHANGE_REASON_REMOTE) .build(); - AtomicBoolean stateUpdated = new AtomicBoolean(); SimpleBasePlayer player = new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + @Override protected State getState() { - return stateUpdated.get() ? updatedState : state; + return playerState; } @Override protected ListenableFuture handleSetPlayWhenReady(boolean playWhenReady) { - stateUpdated.set(true); + playerState = updatedState; return Futures.immediateVoidFuture(); } }; @@ -1941,6 +1946,1506 @@ public class SimpleBasePlayerTest { assertThat(callForwarded.get()).isFalse(); } + @SuppressWarnings("deprecation") // Verifying deprecated listener call. + @Test + public void prepare_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setPlaybackState(Player.STATE_IDLE) + .setPlaylist( + ImmutableList.of( + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build())) + .build(); + State updatedState = state.buildUpon().setPlaybackState(Player.STATE_READY).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handlePrepare() { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.prepare(); + + assertThat(player.getPlaybackState()).isEqualTo(Player.STATE_READY); + verify(listener).onPlaybackStateChanged(Player.STATE_READY); + verify(listener) + .onPlayerStateChanged(/* playWhenReady= */ false, /* playbackState= */ Player.STATE_READY); + verifyNoMoreInteractions(listener); + } + + @SuppressWarnings("deprecation") // Verifying deprecated listener call. + @Test + public void prepare_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setPlaybackState(Player.STATE_IDLE) + .setPlaylist( + ImmutableList.of( + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build())) + .build(); + State updatedState = state.buildUpon().setPlaybackState(Player.STATE_READY).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handlePrepare() { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.prepare(); + + // Verify placeholder state and listener calls. + assertThat(player.getPlaybackState()).isEqualTo(Player.STATE_BUFFERING); + verify(listener).onPlaybackStateChanged(Player.STATE_BUFFERING); + verify(listener) + .onPlayerStateChanged( + /* playWhenReady= */ false, /* playbackState= */ Player.STATE_BUFFERING); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getPlaybackState()).isEqualTo(Player.STATE_READY); + verify(listener).onPlaybackStateChanged(Player.STATE_READY); + verify(listener) + .onPlayerStateChanged(/* playWhenReady= */ false, /* playbackState= */ Player.STATE_READY); + verifyNoMoreInteractions(listener); + } + + @Test + public void prepare_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder().addAllCommands().remove(Player.COMMAND_PREPARE).build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handlePrepare() { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.prepare(); + + assertThat(callForwarded.get()).isFalse(); + } + + @SuppressWarnings("deprecation") // Verifying deprecated listener call. + @Test + public void stop_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setPlaybackState(Player.STATE_READY) + .setPlaylist( + ImmutableList.of( + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build())) + .build(); + State updatedState = state.buildUpon().setPlaybackState(Player.STATE_IDLE).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleStop() { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.stop(); + + assertThat(player.getPlaybackState()).isEqualTo(Player.STATE_IDLE); + verify(listener).onPlaybackStateChanged(Player.STATE_IDLE); + verify(listener) + .onPlayerStateChanged(/* playWhenReady= */ false, /* playbackState= */ Player.STATE_IDLE); + verifyNoMoreInteractions(listener); + } + + @SuppressWarnings("deprecation") // Verifying deprecated listener call. + @Test + public void stop_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setPlaybackState(Player.STATE_READY) + .setPlaylist( + ImmutableList.of( + new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build())) + .build(); + // Additionally set the repeat mode to see a difference between the placeholder and new state. + State updatedState = + state + .buildUpon() + .setPlaybackState(Player.STATE_IDLE) + .setRepeatMode(Player.REPEAT_MODE_ALL) + .build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleStop() { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.stop(); + + // Verify placeholder state and listener calls. + assertThat(player.getPlaybackState()).isEqualTo(Player.STATE_IDLE); + assertThat(player.getRepeatMode()).isEqualTo(Player.REPEAT_MODE_OFF); + verify(listener).onPlaybackStateChanged(Player.STATE_IDLE); + verify(listener) + .onPlayerStateChanged(/* playWhenReady= */ false, /* playbackState= */ Player.STATE_IDLE); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getRepeatMode()).isEqualTo(Player.REPEAT_MODE_ALL); + verify(listener).onRepeatModeChanged(Player.REPEAT_MODE_ALL); + verifyNoMoreInteractions(listener); + } + + @Test + public void stop_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder().addAllCommands().remove(Player.COMMAND_STOP).build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleStop() { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.stop(); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void setRepeatMode_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a different one to the one requested to ensure the updated state is used. + State updatedState = state.buildUpon().setRepeatMode(Player.REPEAT_MODE_ALL).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleSetRepeatMode(@Player.RepeatMode int repeatMode) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setRepeatMode(Player.REPEAT_MODE_ONE); + + assertThat(player.getRepeatMode()).isEqualTo(Player.REPEAT_MODE_ALL); + verify(listener).onRepeatModeChanged(Player.REPEAT_MODE_ALL); + verifyNoMoreInteractions(listener); + } + + @Test + public void setRepeatMode_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a new repeat mode to see a difference between the placeholder and new state. + State updatedState = state.buildUpon().setRepeatMode(Player.REPEAT_MODE_ALL).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleSetRepeatMode(@Player.RepeatMode int repeatMode) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setRepeatMode(Player.REPEAT_MODE_ONE); + + // Verify placeholder state and listener calls. + assertThat(player.getRepeatMode()).isEqualTo(Player.REPEAT_MODE_ONE); + verify(listener).onRepeatModeChanged(Player.REPEAT_MODE_ONE); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getRepeatMode()).isEqualTo(Player.REPEAT_MODE_ALL); + verify(listener).onRepeatModeChanged(Player.REPEAT_MODE_ALL); + verifyNoMoreInteractions(listener); + } + + @Test + public void setRepeatMode_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_SET_REPEAT_MODE) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleSetRepeatMode(@Player.RepeatMode int repeatMode) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.setRepeatMode(Player.REPEAT_MODE_ONE); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void setShuffleModeEnabled_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Also change the repeat mode to ensure the updated state is used. + State updatedState = + state.buildUpon().setShuffleModeEnabled(true).setRepeatMode(Player.REPEAT_MODE_ALL).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleSetShuffleModeEnabled(boolean shuffleModeEnabled) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setShuffleModeEnabled(true); + + assertThat(player.getShuffleModeEnabled()).isTrue(); + assertThat(player.getRepeatMode()).isEqualTo(Player.REPEAT_MODE_ALL); + verify(listener).onShuffleModeEnabledChanged(true); + verify(listener).onRepeatModeChanged(Player.REPEAT_MODE_ALL); + verifyNoMoreInteractions(listener); + } + + @Test + public void setShuffleModeEnabled_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + // Always return the same state to revert the shuffle mode change. This allows to see a + // difference between the placeholder and new state. + return state; + } + + @Override + protected ListenableFuture handleSetShuffleModeEnabled(boolean shuffleModeEnabled) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setShuffleModeEnabled(true); + + // Verify placeholder state and listener calls. + assertThat(player.getShuffleModeEnabled()).isTrue(); + verify(listener).onShuffleModeEnabledChanged(true); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getShuffleModeEnabled()).isFalse(); + verify(listener).onShuffleModeEnabledChanged(false); + verifyNoMoreInteractions(listener); + } + + @Test + public void setShuffleModeEnabled_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_SET_SHUFFLE_MODE) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleSetShuffleModeEnabled(boolean shuffleModeEnabled) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.setShuffleModeEnabled(true); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void setPlaybackParameters_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a different one to the one requested to ensure the updated state is used. + State updatedState = + state.buildUpon().setPlaybackParameters(new PlaybackParameters(/* speed= */ 3f)).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleSetPlaybackParameters( + PlaybackParameters playbackParameters) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setPlaybackParameters(new PlaybackParameters(/* speed= */ 2f)); + + assertThat(player.getPlaybackParameters()).isEqualTo(new PlaybackParameters(/* speed= */ 3f)); + verify(listener).onPlaybackParametersChanged(new PlaybackParameters(/* speed= */ 3f)); + verifyNoMoreInteractions(listener); + } + + @Test + public void setPlaybackParameters_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a new repeat mode to see a difference between the placeholder and new state. + State updatedState = + state.buildUpon().setPlaybackParameters(new PlaybackParameters(/* speed= */ 3f)).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleSetPlaybackParameters( + PlaybackParameters playbackParameters) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setPlaybackParameters(new PlaybackParameters(/* speed= */ 2f)); + + // Verify placeholder state and listener calls. + assertThat(player.getPlaybackParameters()).isEqualTo(new PlaybackParameters(/* speed= */ 2f)); + verify(listener).onPlaybackParametersChanged(new PlaybackParameters(/* speed= */ 2f)); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getPlaybackParameters()).isEqualTo(new PlaybackParameters(/* speed= */ 3f)); + verify(listener).onPlaybackParametersChanged(new PlaybackParameters(/* speed= */ 3f)); + verifyNoMoreInteractions(listener); + } + + @Test + public void setPlaybackParameters_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_SET_SPEED_AND_PITCH) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleSetPlaybackParameters( + PlaybackParameters playbackParameters) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.setPlaybackParameters(new PlaybackParameters(/* speed= */ 2f)); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void setTrackSelectionParameters_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a different one to the one requested to ensure the updated state is used. + TrackSelectionParameters updatedParameters = + new TrackSelectionParameters.Builder(ApplicationProvider.getApplicationContext()) + .setMaxVideoBitrate(3000) + .build(); + State updatedState = state.buildUpon().setTrackSelectionParameters(updatedParameters).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleSetTrackSelectionParameters( + TrackSelectionParameters trackSelectionParameters) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setTrackSelectionParameters( + new TrackSelectionParameters.Builder(ApplicationProvider.getApplicationContext()) + .setMaxVideoBitrate(1000) + .build()); + + assertThat(player.getTrackSelectionParameters()).isEqualTo(updatedParameters); + verify(listener).onTrackSelectionParametersChanged(updatedParameters); + verifyNoMoreInteractions(listener); + } + + @Test + public void setTrackSelectionParameters_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set new parameters to see a difference between the placeholder and new state. + TrackSelectionParameters updatedParameters = + new TrackSelectionParameters.Builder(ApplicationProvider.getApplicationContext()) + .setMaxVideoBitrate(3000) + .build(); + State updatedState = state.buildUpon().setTrackSelectionParameters(updatedParameters).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleSetTrackSelectionParameters( + TrackSelectionParameters trackSelectionParameters) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + TrackSelectionParameters requestedParameters = + new TrackSelectionParameters.Builder(ApplicationProvider.getApplicationContext()) + .setMaxVideoBitrate(3000) + .build(); + player.setTrackSelectionParameters(requestedParameters); + + // Verify placeholder state and listener calls. + assertThat(player.getTrackSelectionParameters()).isEqualTo(requestedParameters); + verify(listener).onTrackSelectionParametersChanged(requestedParameters); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getTrackSelectionParameters()).isEqualTo(updatedParameters); + verify(listener).onTrackSelectionParametersChanged(updatedParameters); + verifyNoMoreInteractions(listener); + } + + @Test + public void setTrackSelectionParameters_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleSetTrackSelectionParameters( + TrackSelectionParameters trackSelectionParameters) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.setTrackSelectionParameters( + new TrackSelectionParameters.Builder(ApplicationProvider.getApplicationContext()) + .setMaxVideoBitrate(1000) + .build()); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void setPlaylistMetadata_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a different one to the one requested to ensure the updated state is used. + MediaMetadata updatedMetadata = new MediaMetadata.Builder().setArtist("artist").build(); + State updatedState = state.buildUpon().setPlaylistMetadata(updatedMetadata).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleSetPlaylistMetadata(MediaMetadata playlistMetadata) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setPlaylistMetadata(new MediaMetadata.Builder().setTitle("title").build()); + + assertThat(player.getPlaylistMetadata()).isEqualTo(updatedMetadata); + verify(listener).onPlaylistMetadataChanged(updatedMetadata); + verifyNoMoreInteractions(listener); + } + + @Test + public void setPlaylistMetadata_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set new metadata to see a difference between the placeholder and new state. + MediaMetadata updatedMetadata = new MediaMetadata.Builder().setArtist("artist").build(); + State updatedState = state.buildUpon().setPlaylistMetadata(updatedMetadata).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleSetPlaylistMetadata(MediaMetadata playlistMetadata) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + MediaMetadata requestedMetadata = new MediaMetadata.Builder().setTitle("title").build(); + player.setPlaylistMetadata(requestedMetadata); + + // Verify placeholder state and listener calls. + assertThat(player.getPlaylistMetadata()).isEqualTo(requestedMetadata); + verify(listener).onPlaylistMetadataChanged(requestedMetadata); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getPlaylistMetadata()).isEqualTo(updatedMetadata); + verify(listener).onPlaylistMetadataChanged(updatedMetadata); + verifyNoMoreInteractions(listener); + } + + @Test + public void setPlaylistMetadata_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_SET_MEDIA_ITEMS_METADATA) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleSetPlaylistMetadata(MediaMetadata playlistMetadata) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.setPlaylistMetadata(new MediaMetadata.Builder().setTitle("title").build()); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void setVolume_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a different one to the one requested to ensure the updated state is used. + State updatedState = state.buildUpon().setVolume(.8f).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleSetVolume(float volume) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setVolume(.5f); + + assertThat(player.getVolume()).isEqualTo(.8f); + verify(listener).onVolumeChanged(.8f); + verifyNoMoreInteractions(listener); + } + + @Test + public void setVolume_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a new volume to see a difference between the placeholder and new state. + State updatedState = state.buildUpon().setVolume(.8f).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleSetVolume(float volume) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setVolume(.5f); + + // Verify placeholder state and listener calls. + assertThat(player.getVolume()).isEqualTo(.5f); + verify(listener).onVolumeChanged(.5f); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getVolume()).isEqualTo(.8f); + verify(listener).onVolumeChanged(.8f); + verifyNoMoreInteractions(listener); + } + + @Test + public void setVolume_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder().addAllCommands().remove(Player.COMMAND_SET_VOLUME).build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleSetVolume(float volume) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.setVolume(.5f); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void setDeviceVolume_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a different one to the one requested to ensure the updated state is used. + State updatedState = state.buildUpon().setDeviceVolume(6).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleSetDeviceVolume(int volume) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setDeviceVolume(3); + + assertThat(player.getDeviceVolume()).isEqualTo(6); + verify(listener).onDeviceVolumeChanged(6, /* muted= */ false); + verifyNoMoreInteractions(listener); + } + + @Test + public void setDeviceVolume_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Set a new volume to see a difference between the placeholder and new state. + State updatedState = state.buildUpon().setDeviceVolume(6).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleSetDeviceVolume(int volume) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setDeviceVolume(3); + + // Verify placeholder state and listener calls. + assertThat(player.getDeviceVolume()).isEqualTo(3); + verify(listener).onDeviceVolumeChanged(3, /* muted= */ false); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getDeviceVolume()).isEqualTo(6); + verify(listener).onDeviceVolumeChanged(6, /* muted= */ false); + verifyNoMoreInteractions(listener); + } + + @Test + public void setDeviceVolume_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_SET_DEVICE_VOLUME) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleSetDeviceVolume(int volume) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.setDeviceVolume(3); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void increaseDeviceVolume_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setDeviceVolume(3) + .build(); + // Set a different one to the one requested to ensure the updated state is used. + State updatedState = state.buildUpon().setDeviceVolume(6).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleIncreaseDeviceVolume() { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.increaseDeviceVolume(); + + assertThat(player.getDeviceVolume()).isEqualTo(6); + verify(listener).onDeviceVolumeChanged(6, /* muted= */ false); + verifyNoMoreInteractions(listener); + } + + @Test + public void increaseDeviceVolume_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setDeviceVolume(3) + .build(); + // Set a new volume to see a difference between the placeholder and new state. + State updatedState = state.buildUpon().setDeviceVolume(6).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleIncreaseDeviceVolume() { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.increaseDeviceVolume(); + + // Verify placeholder state and listener calls. + assertThat(player.getDeviceVolume()).isEqualTo(4); + verify(listener).onDeviceVolumeChanged(4, /* muted= */ false); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getDeviceVolume()).isEqualTo(6); + verify(listener).onDeviceVolumeChanged(6, /* muted= */ false); + verifyNoMoreInteractions(listener); + } + + @Test + public void increaseDeviceVolume_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_ADJUST_DEVICE_VOLUME) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleIncreaseDeviceVolume() { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.increaseDeviceVolume(); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void decreaseDeviceVolume_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setDeviceVolume(3) + .build(); + // Set a different one to the one requested to ensure the updated state is used. + State updatedState = state.buildUpon().setDeviceVolume(1).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleDecreaseDeviceVolume() { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.decreaseDeviceVolume(); + + assertThat(player.getDeviceVolume()).isEqualTo(1); + verify(listener).onDeviceVolumeChanged(1, /* muted= */ false); + verifyNoMoreInteractions(listener); + } + + @Test + public void decreaseDeviceVolume_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setDeviceVolume(3) + .build(); + // Set a new volume to see a difference between the placeholder and new state. + State updatedState = state.buildUpon().setDeviceVolume(1).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleDecreaseDeviceVolume() { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.decreaseDeviceVolume(); + + // Verify placeholder state and listener calls. + assertThat(player.getDeviceVolume()).isEqualTo(2); + verify(listener).onDeviceVolumeChanged(2, /* muted= */ false); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getDeviceVolume()).isEqualTo(1); + verify(listener).onDeviceVolumeChanged(1, /* muted= */ false); + verifyNoMoreInteractions(listener); + } + + @Test + public void decreaseDeviceVolume_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_ADJUST_DEVICE_VOLUME) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleDecreaseDeviceVolume() { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.decreaseDeviceVolume(); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void setDeviceMuted_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + // Also change the volume to ensure the updated state is used. + State updatedState = state.buildUpon().setIsDeviceMuted(true).setDeviceVolume(6).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleSetDeviceMuted(boolean muted) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setDeviceMuted(true); + + assertThat(player.isDeviceMuted()).isTrue(); + assertThat(player.getDeviceVolume()).isEqualTo(6); + verify(listener).onDeviceVolumeChanged(6, /* muted= */ true); + verifyNoMoreInteractions(listener); + } + + @Test + public void setDeviceMuted_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + // Always return the same state to revert the muted change. This allows to see a + // difference between the placeholder and new state. + return state; + } + + @Override + protected ListenableFuture handleSetDeviceMuted(boolean muted) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setDeviceMuted(true); + + // Verify placeholder state and listener calls. + assertThat(player.isDeviceMuted()).isTrue(); + verify(listener).onDeviceVolumeChanged(0, /* muted= */ true); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.isDeviceMuted()).isFalse(); + verify(listener).onDeviceVolumeChanged(0, /* muted= */ false); + verifyNoMoreInteractions(listener); + } + + @Test + public void setDeviceMuted_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_ADJUST_DEVICE_VOLUME) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleSetDeviceMuted(boolean muted) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.setDeviceMuted(true); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void setVideoSurface_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setSurfaceSize(Size.ZERO) + .build(); + Size updatedSize = new Size(/* width= */ 300, /* height= */ 200); + State updatedState = state.buildUpon().setSurfaceSize(updatedSize).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleSetVideoOutput(Object videoOutput) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setVideoSurface(new Surface(new SurfaceTexture(0))); + + assertThat(player.getSurfaceSize()).isEqualTo(updatedSize); + verify(listener).onSurfaceSizeChanged(updatedSize.getWidth(), updatedSize.getHeight()); + verifyNoMoreInteractions(listener); + } + + @Test + public void setVideoSurface_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setSurfaceSize(Size.ZERO) + .build(); + SettableFuture future = SettableFuture.create(); + Size updatedSize = new Size(/* width= */ 300, /* height= */ 200); + State updatedState = state.buildUpon().setSurfaceSize(updatedSize).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleSetVideoOutput(Object videoOutput) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.setVideoSurface(new Surface(new SurfaceTexture(0))); + + // Verify placeholder state and listener calls. + assertThat(player.getSurfaceSize()).isEqualTo(Size.UNKNOWN); + verify(listener) + .onSurfaceSizeChanged(/* width= */ C.LENGTH_UNSET, /* height= */ C.LENGTH_UNSET); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getSurfaceSize()).isEqualTo(updatedSize); + verify(listener).onSurfaceSizeChanged(updatedSize.getWidth(), updatedSize.getHeight()); + verifyNoMoreInteractions(listener); + } + + @Test + public void setVideoSurface_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_SET_VIDEO_SURFACE) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleSetVideoOutput(Object videoOutput) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.setVideoSurface(new Surface(new SurfaceTexture(0))); + + assertThat(callForwarded.get()).isFalse(); + } + + @Test + public void clearVideoSurface_immediateHandling_updatesStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setSurfaceSize(new Size(/* width= */ 300, /* height= */ 200)) + .build(); + // Change something else in addition to ensure we actually use the updated state. + State updatedState = + state.buildUpon().setSurfaceSize(Size.ZERO).setRepeatMode(Player.REPEAT_MODE_ONE).build(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + private State playerState = state; + + @Override + protected State getState() { + return playerState; + } + + @Override + protected ListenableFuture handleClearVideoOutput(@Nullable Object videoOutput) { + playerState = updatedState; + return Futures.immediateVoidFuture(); + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.clearVideoSurface(); + + assertThat(player.getSurfaceSize()).isEqualTo(Size.ZERO); + assertThat(player.getRepeatMode()).isEqualTo(Player.REPEAT_MODE_ONE); + verify(listener).onSurfaceSizeChanged(/* width= */ 0, /* height= */ 0); + verify(listener).onRepeatModeChanged(Player.REPEAT_MODE_ONE); + verifyNoMoreInteractions(listener); + } + + @Test + public void clearVideoSurface_asyncHandling_usesPlaceholderStateAndInformsListeners() { + State state = + new State.Builder() + .setAvailableCommands(new Commands.Builder().addAllCommands().build()) + .setSurfaceSize(new Size(/* width= */ 300, /* height= */ 200)) + .build(); + // Change something else in addition to ensure we actually use the updated state. + State updatedState = + state.buildUpon().setSurfaceSize(Size.ZERO).setRepeatMode(Player.REPEAT_MODE_ONE).build(); + SettableFuture future = SettableFuture.create(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return future.isDone() ? updatedState : state; + } + + @Override + protected ListenableFuture handleClearVideoOutput(@Nullable Object videoOutput) { + return future; + } + }; + Listener listener = mock(Listener.class); + player.addListener(listener); + + player.clearVideoSurface(); + + // Verify placeholder state and listener calls. + assertThat(player.getSurfaceSize()).isEqualTo(Size.ZERO); + verify(listener).onSurfaceSizeChanged(/* width= */ 0, /* height= */ 0); + verifyNoMoreInteractions(listener); + + future.set(null); + + // Verify actual state update. + assertThat(player.getSurfaceSize()).isEqualTo(Size.ZERO); + assertThat(player.getRepeatMode()).isEqualTo(Player.REPEAT_MODE_ONE); + verify(listener).onRepeatModeChanged(Player.REPEAT_MODE_ONE); + verifyNoMoreInteractions(listener); + } + + @Test + public void clearVideoSurface_withoutAvailableCommand_isNotForwarded() { + State state = + new State.Builder() + .setAvailableCommands( + new Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_SET_VIDEO_SURFACE) + .build()) + .build(); + AtomicBoolean callForwarded = new AtomicBoolean(); + SimpleBasePlayer player = + new SimpleBasePlayer(Looper.myLooper()) { + @Override + protected State getState() { + return state; + } + + @Override + protected ListenableFuture handleClearVideoOutput(@Nullable Object videoOutput) { + callForwarded.set(true); + return Futures.immediateVoidFuture(); + } + }; + + player.clearVideoSurface(); + + assertThat(callForwarded.get()).isFalse(); + } + private static Object[] getAnyArguments(Method method) { Object[] arguments = new Object[method.getParameterCount()]; Class[] argumentTypes = method.getParameterTypes(); From 90d4fdcf0f4a3cb7b6c8cfeebc79f3f3db7eab31 Mon Sep 17 00:00:00 2001 From: kimvde Date: Thu, 1 Dec 2022 09:21:54 +0000 Subject: [PATCH 036/183] Fix gradle build Add required import for androidx.window.java.layout.WindowInfoTrackerCallbackAdapter PiperOrigin-RevId: 492131661 --- library/ui/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui/build.gradle b/library/ui/build.gradle index c7c990069d..266111709a 100644 --- a/library/ui/build.gradle +++ b/library/ui/build.gradle @@ -28,6 +28,7 @@ dependencies { implementation 'androidx.core:core:' + androidxCoreVersion implementation 'androidx.recyclerview:recyclerview:' + androidxRecyclerViewVersion implementation 'androidx.window:window:' + androidxWindowVersion + implementation 'androidx.window:window-java:' + androidxWindowVersion compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion testImplementation project(modulePrefix + 'testutils') From 32bed82897e8cafce66fd7efcd7d6e30fcad4859 Mon Sep 17 00:00:00 2001 From: samrobinson Date: Thu, 1 Dec 2022 11:45:40 +0000 Subject: [PATCH 037/183] Add an option to force a silent audio track. PiperOrigin-RevId: 492154544 --- .../AudioTranscodingSamplePipeline.java | 66 ++- .../transformer/SilentAudioGenerator.java | 51 ++ .../exoplayer2/transformer/Transformer.java | 41 +- .../transformer/TransformerInternal.java | 36 ++ .../transformer/SilentAudioGeneratorTest.java | 73 +++ .../transformer/TransformerEndToEndTest.java | 15 + .../mp4/sample.mp4.silentaudio.dump | 467 ++++++++++++++++++ 7 files changed, 744 insertions(+), 5 deletions(-) create mode 100644 library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SilentAudioGenerator.java create mode 100644 library/transformer/src/test/java/com/google/android/exoplayer2/transformer/SilentAudioGeneratorTest.java create mode 100644 testdata/src/test/assets/transformerdumps/mp4/sample.mp4.silentaudio.dump diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java index 918561d111..e6ba26a882 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java @@ -41,6 +41,7 @@ import org.checkerframework.dataflow.qual.Pure; private static final int DEFAULT_ENCODER_BITRATE = 128 * 1024; + @Nullable private final SilentAudioGenerator silentAudioGenerator; private final DecoderInputBuffer inputBuffer; private final AudioProcessingPipeline audioProcessingPipeline; private final Codec encoder; @@ -52,12 +53,14 @@ import org.checkerframework.dataflow.qual.Pure; private long nextEncoderInputBufferTimeUs; private long encoderBufferDurationRemainder; + // TODO(b/260618558): Move silent audio generation upstream of this component. public AudioTranscodingSamplePipeline( Format inputFormat, long streamStartPositionUs, long streamOffsetUs, TransformationRequest transformationRequest, ImmutableList audioProcessors, + long forceSilentAudioDurationUs, Codec.EncoderFactory encoderFactory, MuxerWrapper muxerWrapper, Listener listener, @@ -71,6 +74,16 @@ import org.checkerframework.dataflow.qual.Pure; muxerWrapper, listener); + if (forceSilentAudioDurationUs != C.TIME_UNSET) { + silentAudioGenerator = + new SilentAudioGenerator( + forceSilentAudioDurationUs, + inputFormat.sampleRate, + Util.getPcmFrameSize(C.ENCODING_PCM_16BIT, inputFormat.channelCount)); + } else { + silentAudioGenerator = null; + } + inputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); encoderInputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); encoderOutputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); @@ -160,11 +173,17 @@ import org.checkerframework.dataflow.qual.Pure; @Override protected boolean processDataUpToMuxer() throws TransformationException { - if (audioProcessingPipeline.isOperational()) { - return feedEncoderFromProcessingPipeline() || feedProcessingPipelineFromInput(); - } else { - return feedEncoderFromInput(); + if (!audioProcessingPipeline.isOperational()) { + return silentAudioGenerator == null ? feedEncoderFromInput() : feedEncoderFromSilence(); } + + if (feedEncoderFromProcessingPipeline()) { + return true; + } + + return silentAudioGenerator == null + ? feedProcessingPipelineFromInput() + : feedProcessingPipelineFromSilence(); } @Override @@ -268,6 +287,45 @@ import org.checkerframework.dataflow.qual.Pure; return true; } + /** + * Attempts to pass silent audio to the encoder. + * + * @return Whether it may be possible to feed more data immediately by calling this method again. + */ + private boolean feedEncoderFromSilence() throws TransformationException { + checkNotNull(silentAudioGenerator); + if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) { + return false; + } + + if (silentAudioGenerator.isEnded()) { + queueEndOfStreamToEncoder(); + return false; + } + + ByteBuffer silence = silentAudioGenerator.getBuffer(); + feedEncoder(silence); + return true; + } + + /** + * Attempts to feed silent audio to the {@link AudioProcessingPipeline}. + * + * @return Whether it may be possible to feed more data immediately by calling this method again. + */ + private boolean feedProcessingPipelineFromSilence() { + checkNotNull(silentAudioGenerator); + if (silentAudioGenerator.isEnded()) { + audioProcessingPipeline.queueEndOfStream(); + return false; + } + checkState(!audioProcessingPipeline.isEnded()); + + ByteBuffer silence = silentAudioGenerator.getBuffer(); + audioProcessingPipeline.queueInput(silence); + return !silence.hasRemaining(); + } + /** * Feeds as much data as possible between the current position and limit of the specified {@link * ByteBuffer} to the encoder, and advances its position by the number of bytes fed. diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SilentAudioGenerator.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SilentAudioGenerator.java new file mode 100644 index 0000000000..ad917b23d5 --- /dev/null +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SilentAudioGenerator.java @@ -0,0 +1,51 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.exoplayer2.transformer; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/* package */ final class SilentAudioGenerator { + private static final int DEFAULT_BUFFER_SIZE = 4096; + + private final ByteBuffer internalBuffer; + + private long remainingBytesToOutput; + + public SilentAudioGenerator(long totalDurationUs, long sampleRate, int frameSize) { + remainingBytesToOutput = (sampleRate * frameSize * totalDurationUs) / 1_000_000L; + internalBuffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE).order(ByteOrder.nativeOrder()); + internalBuffer.flip(); + } + + public ByteBuffer getBuffer() { + if (!internalBuffer.hasRemaining()) { + // "next" buffer. + internalBuffer.clear(); + if (remainingBytesToOutput < internalBuffer.capacity()) { + internalBuffer.limit((int) remainingBytesToOutput); + } + // Only reduce remaining bytes when we "generate" a new one. + remainingBytesToOutput -= internalBuffer.remaining(); + } + return internalBuffer; + } + + public boolean isEnded() { + return !internalBuffer.hasRemaining() && remainingBytesToOutput == 0; + } +} 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 b235833df0..340d4b4254 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 @@ -30,6 +30,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.audio.AudioProcessor; +import com.google.android.exoplayer2.audio.SonicAudioProcessor; import com.google.android.exoplayer2.effect.GlEffect; import com.google.android.exoplayer2.effect.GlEffectsFrameProcessor; import com.google.android.exoplayer2.effect.GlMatrixTransformation; @@ -86,6 +87,7 @@ public final class Transformer { private ImmutableList videoEffects; private boolean removeAudio; private boolean removeVideo; + private boolean forceSilentAudio; private ListenerSet listeners; private MediaSource.@MonotonicNonNull Factory mediaSourceFactory; private Codec.DecoderFactory decoderFactory; @@ -124,6 +126,7 @@ public final class Transformer { this.videoEffects = transformer.videoEffects; this.removeAudio = transformer.removeAudio; this.removeVideo = transformer.removeVideo; + this.forceSilentAudio = transformer.forceSilentAudio; this.listeners = transformer.listeners; this.mediaSourceFactory = transformer.mediaSourceFactory; this.decoderFactory = transformer.decoderFactory; @@ -414,6 +417,33 @@ public final class Transformer { return this; } + /** + * Sets whether to force silent audio for the output file, ignoring any existing audio. + * + *

This method is experimental and may be removed or changed without warning. + * + *

Audio properties/format: + * + *

    + *
  • Duration will match duration of the input media. + *
  • Sample mime type will match {@link TransformationRequest#audioMimeType}, or {@link + * MimeTypes#AUDIO_AAC} if {@code null}. + *
  • Sample rate will be 44100hz. This can be modified by passing a {@link + * SonicAudioProcessor} to {@link #setAudioProcessors(List)}, using {@link + * SonicAudioProcessor#setOutputSampleRateHz(int)}. + *
  • Channel count will be 2. This can be modified by implementing a custom {@link + * AudioProcessor} and passing it to {@link #setAudioProcessors(List)}. + *
+ * + * @param forceSilentAudio Whether to output silent audio for the output file. + * @return This builder. + */ + @CanIgnoreReturnValue + public Builder experimentalSetForceSilentAudio(boolean forceSilentAudio) { + this.forceSilentAudio = forceSilentAudio; + return this; + } + /** * Builds a {@link Transformer} instance. * @@ -443,6 +473,7 @@ public final class Transformer { videoEffects, removeAudio, removeVideo, + forceSilentAudio, listeners, mediaSourceFactory, decoderFactory, @@ -555,6 +586,7 @@ public final class Transformer { private final ImmutableList videoEffects; private final boolean removeAudio; private final boolean removeVideo; + private final boolean forceSilentAudio; private final ListenerSet listeners; private final MediaSource.Factory mediaSourceFactory; private final FrameProcessor.Factory frameProcessorFactory; @@ -572,7 +604,8 @@ public final class Transformer { ImmutableList videoEffects, boolean removeAudio, boolean removeVideo, - ListenerSet listeners, + boolean forceSilentAudio, + ListenerSet listeners, MediaSource.Factory mediaSourceFactory, Codec.DecoderFactory decoderFactory, Codec.EncoderFactory encoderFactory, @@ -581,6 +614,10 @@ public final class Transformer { Looper looper, DebugViewProvider debugViewProvider, Clock clock) { + if (forceSilentAudio) { + removeAudio = true; + } + checkState(!removeVideo || !forceSilentAudio, "Silent only audio track needs a video track."); checkState(!removeAudio || !removeVideo, "Audio and video cannot both be removed."); this.context = context; this.transformationRequest = transformationRequest; @@ -588,6 +625,7 @@ public final class Transformer { this.videoEffects = videoEffects; this.removeAudio = removeAudio; this.removeVideo = removeVideo; + this.forceSilentAudio = forceSilentAudio; this.listeners = listeners; this.mediaSourceFactory = mediaSourceFactory; this.decoderFactory = decoderFactory; @@ -726,6 +764,7 @@ public final class Transformer { videoEffects, removeAudio, removeVideo, + forceSilentAudio, mediaSourceFactory, decoderFactory, encoderFactory, diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java index 30216dcac6..5dad73f446 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java @@ -97,6 +97,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private final TransformationRequest transformationRequest; private final ImmutableList audioProcessors; private final ImmutableList videoEffects; + private final boolean forceSilentAudio; private final Codec.DecoderFactory decoderFactory; private final Codec.EncoderFactory encoderFactory; private final FrameProcessor.Factory frameProcessorFactory; @@ -114,6 +115,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Nullable private DecoderInputBuffer pendingInputBuffer; private boolean isDrainingPipelines; + private int silentSamplePipelineIndex; private @Transformer.ProgressState int progressState; private long progressPositionMs; private long durationUs; @@ -131,6 +133,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ImmutableList videoEffects, boolean removeAudio, boolean removeVideo, + boolean forceSilentAudio, MediaSource.Factory mediaSourceFactory, Codec.DecoderFactory decoderFactory, Codec.EncoderFactory encoderFactory, @@ -145,6 +148,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; this.transformationRequest = transformationRequest; this.audioProcessors = audioProcessors; this.videoEffects = videoEffects; + this.forceSilentAudio = forceSilentAudio; this.decoderFactory = decoderFactory; this.encoderFactory = encoderFactory; this.frameProcessorFactory = frameProcessorFactory; @@ -168,6 +172,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; componentListener, clock); samplePipelines = new ArrayList<>(); + silentSamplePipelineIndex = C.INDEX_UNSET; dequeueBufferConditionVariable = new ConditionVariable(); muxerWrapper = new MuxerWrapper( @@ -258,6 +263,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; while (samplePipeline.processData()) {} pendingInputBuffer = samplePipeline.dequeueInputBuffer(); dequeueBufferConditionVariable.open(); + + if (forceSilentAudio) { + while (samplePipelines.get(silentSamplePipelineIndex).processData()) {} + } } private void queueInputInternal(int samplePipelineIndex) throws TransformationException { @@ -391,6 +400,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; trackRegistered = true; muxerWrapper.registerTrack(); fallbackListener.registerTrack(); + + if (forceSilentAudio) { + muxerWrapper.registerTrack(); + fallbackListener.registerTrack(); + } } @Override @@ -410,6 +424,23 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; int samplePipelineIndex = tracksAddedCount; tracksAddedCount++; + + if (forceSilentAudio) { + Format silentAudioFormat = + new Format.Builder() + .setSampleMimeType(MimeTypes.AUDIO_AAC) + .setSampleRate(44100) + .setChannelCount(2) + .build(); + SamplePipeline audioSamplePipeline = + getSamplePipeline(silentAudioFormat, streamStartPositionUs, streamOffsetUs); + internalHandler + .obtainMessage(MSG_REGISTER_SAMPLE_PIPELINE, audioSamplePipeline) + .sendToTarget(); + silentSamplePipelineIndex = tracksAddedCount; + tracksAddedCount++; + } + return new SamplePipelineInput(samplePipelineIndex, samplePipeline.expectsDecodedData()); } @@ -459,6 +490,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; streamOffsetUs, transformationRequest, audioProcessors, + forceSilentAudio ? durationUs : C.TIME_UNSET, encoderFactory, muxerWrapper, /* listener= */ this, @@ -509,6 +541,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; if (!audioProcessors.isEmpty()) { return true; } + if (forceSilentAudio) { + return true; + } + return false; } diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/SilentAudioGeneratorTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/SilentAudioGeneratorTest.java new file mode 100644 index 0000000000..a98f608c77 --- /dev/null +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/SilentAudioGeneratorTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.transformer; + +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import java.nio.ByteBuffer; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit tests for {@link SilentAudioGenerator}. */ +@RunWith(AndroidJUnit4.class) +public class SilentAudioGeneratorTest { + + @Test + public void numberOfBytesProduced_isCorrect() { + SilentAudioGenerator generator = + new SilentAudioGenerator( + /* totalDurationUs= */ 3_000_000, /* sampleRate= */ 88_200, /* frameSize= */ 12); + int bytesOutput = 0; + while (!generator.isEnded()) { + ByteBuffer output = generator.getBuffer(); + bytesOutput += output.remaining(); + // "Consume" buffer. + output.position(output.limit()); + } + + // 88_200 * 12 * 3s = 3175200 + assertThat(bytesOutput).isEqualTo(3_175_200); + } + + @Test + public void lastBufferProduced_isCorrectSize() { + SilentAudioGenerator generator = + new SilentAudioGenerator( + /* totalDurationUs= */ 1_000_000, /* sampleRate= */ 44_100, /* frameSize= */ 4); + + int currentBufferSize = 0; + while (!generator.isEnded()) { + ByteBuffer output = generator.getBuffer(); + currentBufferSize = output.remaining(); + // "Consume" buffer. + output.position(output.limit()); + } + + // Last buffer is smaller and only outputs the 'leftover' bytes. + // (44_100 * 4) % 4096 = 272 + assertThat(currentBufferSize).isEqualTo(272); + } + + @Test + public void totalBytesLowerThanDefaultBufferSize_smallBufferProduced() { + SilentAudioGenerator generator = + new SilentAudioGenerator( + /* totalDurationUs= */ 5_000, /* sampleRate= */ 48_000, /* frameSize= */ 4); + // 5_000 * 48_000 * 4 / 1_000_000 = 960 + assertThat(generator.getBuffer().remaining()).isEqualTo(960); + } +} diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index 7b9ce8c343..7abf73c5f1 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -265,6 +265,21 @@ public final class TransformerEndToEndTest { context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".novideo")); } + @Test + public void startTransformation_silentAudio_completesSuccessfully() throws Exception { + Transformer transformer = + createTransformerBuilder(/* enableFallback= */ false) + .experimentalSetForceSilentAudio(true) + .build(); + MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO); + + transformer.startTransformation(mediaItem, outputPath); + TransformerTestRunner.runUntilCompleted(transformer); + + DumpFileAsserts.assertOutput( + context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".silentaudio")); + } + @Test public void startTransformation_withMultipleListeners_callsEachOnCompletion() throws Exception { Transformer.Listener mockListener1 = mock(Transformer.Listener.class); diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.silentaudio.dump b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.silentaudio.dump new file mode 100644 index 0000000000..f4685803b7 --- /dev/null +++ b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.silentaudio.dump @@ -0,0 +1,467 @@ +format 0: + id = 1 + sampleMimeType = video/avc + codecs = avc1.64001F + maxInputSize = 36722 + width = 1080 + height = 720 + frameRate = 29.970028 + initializationData: + data = length 29, hash 4746B5D9 + data = length 10, hash 7A0D0F2B +format 1: + sampleMimeType = audio/mp4a-latm + channelCount = 2 + sampleRate = 44100 + pcmEncoding = 2 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 0 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 23220 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 46440 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 69660 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 92880 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 116100 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 139320 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 162540 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 185760 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 208980 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 232200 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 255420 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 278640 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 301860 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 325080 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 348300 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 371520 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 394740 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 417960 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 441180 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 464400 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 487620 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 510840 +sample: + trackIndex = 0 + dataHashCode = -770308242 + size = 36692 + isKeyFrame = true + presentationTimeUs = 0 +sample: + trackIndex = 0 + dataHashCode = -732087136 + size = 5312 + isKeyFrame = false + presentationTimeUs = 66733 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 534059 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 557279 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 580499 +sample: + trackIndex = 0 + dataHashCode = 468156717 + size = 599 + isKeyFrame = false + presentationTimeUs = 33366 +sample: + trackIndex = 0 + dataHashCode = 1150349584 + size = 7735 + isKeyFrame = false + presentationTimeUs = 200200 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 603719 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 626939 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 650159 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 673379 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 696599 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 719819 +sample: + trackIndex = 0 + dataHashCode = 1443582006 + size = 987 + isKeyFrame = false + presentationTimeUs = 133466 +sample: + trackIndex = 0 + dataHashCode = -310585145 + size = 673 + isKeyFrame = false + presentationTimeUs = 100100 +sample: + trackIndex = 0 + dataHashCode = 807460688 + size = 523 + isKeyFrame = false + presentationTimeUs = 166833 +sample: + trackIndex = 0 + dataHashCode = 1936487090 + size = 6061 + isKeyFrame = false + presentationTimeUs = 333666 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 743039 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 766259 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 789479 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 812699 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 835919 +sample: + trackIndex = 0 + dataHashCode = -32297181 + size = 992 + isKeyFrame = false + presentationTimeUs = 266933 +sample: + trackIndex = 0 + dataHashCode = 1529616406 + size = 623 + isKeyFrame = false + presentationTimeUs = 233566 +sample: + trackIndex = 0 + dataHashCode = 1949198785 + size = 421 + isKeyFrame = false + presentationTimeUs = 300300 +sample: + trackIndex = 0 + dataHashCode = -147880287 + size = 4899 + isKeyFrame = false + presentationTimeUs = 433766 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 859139 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 882359 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 905579 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 928799 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 952019 +sample: + trackIndex = 0 + dataHashCode = 1369083472 + size = 568 + isKeyFrame = false + presentationTimeUs = 400400 +sample: + trackIndex = 0 + dataHashCode = 965782073 + size = 620 + isKeyFrame = false + presentationTimeUs = 367033 +sample: + trackIndex = 0 + dataHashCode = -261176150 + size = 5450 + isKeyFrame = false + presentationTimeUs = 567233 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 975239 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 998459 +sample: + trackIndex = 1 + dataHashCode = -1029274849 + size = 409 + isKeyFrame = true + presentationTimeUs = 1021679 +sample: + trackIndex = 0 + dataHashCode = -1830836678 + size = 1051 + isKeyFrame = false + presentationTimeUs = 500500 +sample: + trackIndex = 0 + dataHashCode = 1767407540 + size = 874 + isKeyFrame = false + presentationTimeUs = 467133 +sample: + trackIndex = 0 + dataHashCode = 918440283 + size = 781 + isKeyFrame = false + presentationTimeUs = 533866 +sample: + trackIndex = 0 + dataHashCode = -1408463661 + size = 4725 + isKeyFrame = false + presentationTimeUs = 700700 +sample: + trackIndex = 0 + dataHashCode = 1569455924 + size = 1022 + isKeyFrame = false + presentationTimeUs = 633966 +sample: + trackIndex = 0 + dataHashCode = -1723778407 + size = 790 + isKeyFrame = false + presentationTimeUs = 600600 +sample: + trackIndex = 0 + dataHashCode = 1578275472 + size = 610 + isKeyFrame = false + presentationTimeUs = 667333 +sample: + trackIndex = 0 + dataHashCode = 1989768395 + size = 2751 + isKeyFrame = false + presentationTimeUs = 834166 +sample: + trackIndex = 0 + dataHashCode = -1215674502 + size = 745 + isKeyFrame = false + presentationTimeUs = 767433 +sample: + trackIndex = 0 + dataHashCode = -814473606 + size = 621 + isKeyFrame = false + presentationTimeUs = 734066 +sample: + trackIndex = 0 + dataHashCode = 498370894 + size = 505 + isKeyFrame = false + presentationTimeUs = 800800 +sample: + trackIndex = 0 + dataHashCode = -1051506468 + size = 1268 + isKeyFrame = false + presentationTimeUs = 967633 +sample: + trackIndex = 0 + dataHashCode = -1025604144 + size = 880 + isKeyFrame = false + presentationTimeUs = 900900 +sample: + trackIndex = 0 + dataHashCode = -913586520 + size = 530 + isKeyFrame = false + presentationTimeUs = 867533 +sample: + trackIndex = 0 + dataHashCode = 1340459242 + size = 568 + isKeyFrame = false + presentationTimeUs = 934266 +released = true From 5d2cc8dc36b51a5e30de76f87c997ddbe238d0aa Mon Sep 17 00:00:00 2001 From: samrobinson Date: Thu, 1 Dec 2022 12:20:54 +0000 Subject: [PATCH 038/183] Add an E2E test for changing sample rate with AudioProcessor. PiperOrigin-RevId: 492160193 --- .../transformer/TransformerEndToEndTest.java | 18 + .../mp4/sample.mp4.48000hz.dump | 473 ++++++++++++++++++ 2 files changed, 491 insertions(+) create mode 100644 testdata/src/test/assets/transformerdumps/mp4/sample.mp4.48000hz.dump diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index 7abf73c5f1..4b04293823 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -43,6 +43,7 @@ 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.audio.SonicAudioProcessor; import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; @@ -280,6 +281,23 @@ public final class TransformerEndToEndTest { context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".silentaudio")); } + @Test + public void startTransformation_adjustSampleRate_completesSuccessfully() throws Exception { + SonicAudioProcessor sonicAudioProcessor = new SonicAudioProcessor(); + sonicAudioProcessor.setOutputSampleRateHz(48000); + Transformer transformer = + createTransformerBuilder(/* enableFallback= */ false) + .setAudioProcessors(ImmutableList.of(sonicAudioProcessor)) + .build(); + MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO); + + transformer.startTransformation(mediaItem, outputPath); + TransformerTestRunner.runUntilCompleted(transformer); + + DumpFileAsserts.assertOutput( + context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".48000hz")); + } + @Test public void startTransformation_withMultipleListeners_callsEachOnCompletion() throws Exception { Transformer.Listener mockListener1 = mock(Transformer.Listener.class); diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.48000hz.dump b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.48000hz.dump new file mode 100644 index 0000000000..b11eb46460 --- /dev/null +++ b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.48000hz.dump @@ -0,0 +1,473 @@ +format 0: + sampleMimeType = audio/mp4a-latm + channelCount = 1 + sampleRate = 48000 + pcmEncoding = 2 +format 1: + id = 1 + sampleMimeType = video/avc + codecs = avc1.64001F + maxInputSize = 36722 + width = 1080 + height = 720 + frameRate = 29.970028 + initializationData: + data = length 29, hash 4746B5D9 + data = length 10, hash 7A0D0F2B +sample: + trackIndex = 1 + dataHashCode = -770308242 + size = 36692 + isKeyFrame = true + presentationTimeUs = 0 +sample: + trackIndex = 1 + dataHashCode = -732087136 + size = 5312 + isKeyFrame = false + presentationTimeUs = 66733 +sample: + trackIndex = 1 + dataHashCode = 468156717 + size = 599 + isKeyFrame = false + presentationTimeUs = 33366 +sample: + trackIndex = 1 + dataHashCode = 1150349584 + size = 7735 + isKeyFrame = false + presentationTimeUs = 200200 +sample: + trackIndex = 1 + dataHashCode = 1443582006 + size = 987 + isKeyFrame = false + presentationTimeUs = 133466 +sample: + trackIndex = 1 + dataHashCode = -310585145 + size = 673 + isKeyFrame = false + presentationTimeUs = 100100 +sample: + trackIndex = 1 + dataHashCode = 807460688 + size = 523 + isKeyFrame = false + presentationTimeUs = 166833 +sample: + trackIndex = 1 + dataHashCode = 1936487090 + size = 6061 + isKeyFrame = false + presentationTimeUs = 333666 +sample: + trackIndex = 1 + dataHashCode = -32297181 + size = 992 + isKeyFrame = false + presentationTimeUs = 266933 +sample: + trackIndex = 1 + dataHashCode = 1529616406 + size = 623 + isKeyFrame = false + presentationTimeUs = 233566 +sample: + trackIndex = 1 + dataHashCode = 1949198785 + size = 421 + isKeyFrame = false + presentationTimeUs = 300300 +sample: + trackIndex = 1 + dataHashCode = -147880287 + size = 4899 + isKeyFrame = false + presentationTimeUs = 433766 +sample: + trackIndex = 1 + dataHashCode = 1369083472 + size = 568 + isKeyFrame = false + presentationTimeUs = 400400 +sample: + trackIndex = 1 + dataHashCode = 965782073 + size = 620 + isKeyFrame = false + presentationTimeUs = 367033 +sample: + trackIndex = 1 + dataHashCode = -261176150 + size = 5450 + isKeyFrame = false + presentationTimeUs = 567233 +sample: + trackIndex = 0 + dataHashCode = 1868041800 + size = 22 + isKeyFrame = true + presentationTimeUs = 0 +sample: + trackIndex = 0 + dataHashCode = 1552866193 + size = 8 + isKeyFrame = true + presentationTimeUs = 230 +sample: + trackIndex = 0 + dataHashCode = 701848493 + size = 160 + isKeyFrame = true + presentationTimeUs = 313 +sample: + trackIndex = 0 + dataHashCode = 2000505720 + size = 206 + isKeyFrame = true + presentationTimeUs = 1980 +sample: + trackIndex = 0 + dataHashCode = 57276327 + size = 222 + isKeyFrame = true + presentationTimeUs = 4125 +sample: + trackIndex = 0 + dataHashCode = 382237408 + size = 228 + isKeyFrame = true + presentationTimeUs = 6438 +sample: + trackIndex = 0 + dataHashCode = 795308374 + size = 228 + isKeyFrame = true + presentationTimeUs = 8813 +sample: + trackIndex = 0 + dataHashCode = 356270426 + size = 224 + isKeyFrame = true + presentationTimeUs = 11188 +sample: + trackIndex = 0 + dataHashCode = 963641614 + size = 244 + isKeyFrame = true + presentationTimeUs = 13521 +sample: + trackIndex = 0 + dataHashCode = 2045272193 + size = 234 + isKeyFrame = true + presentationTimeUs = 16063 +sample: + trackIndex = 0 + dataHashCode = -251933090 + size = 228 + isKeyFrame = true + presentationTimeUs = 18500 +sample: + trackIndex = 0 + dataHashCode = -329315280 + size = 234 + isKeyFrame = true + presentationTimeUs = 20875 +sample: + trackIndex = 0 + dataHashCode = -1536715689 + size = 248 + isKeyFrame = true + presentationTimeUs = 23313 +sample: + trackIndex = 0 + dataHashCode = -1275249610 + size = 254 + isKeyFrame = true + presentationTimeUs = 25896 +sample: + trackIndex = 0 + dataHashCode = -2081231470 + size = 254 + isKeyFrame = true + presentationTimeUs = 28542 +sample: + trackIndex = 0 + dataHashCode = 1912348529 + size = 250 + isKeyFrame = true + presentationTimeUs = 31188 +sample: + trackIndex = 0 + dataHashCode = -1393642278 + size = 246 + isKeyFrame = true + presentationTimeUs = 33792 +sample: + trackIndex = 0 + dataHashCode = -2073671562 + size = 236 + isKeyFrame = true + presentationTimeUs = 36355 +sample: + trackIndex = 0 + dataHashCode = -381095129 + size = 248 + isKeyFrame = true + presentationTimeUs = 38813 +sample: + trackIndex = 0 + dataHashCode = -804721381 + size = 238 + isKeyFrame = true + presentationTimeUs = 41396 +sample: + trackIndex = 0 + dataHashCode = 172275944 + size = 260 + isKeyFrame = true + presentationTimeUs = 43875 +sample: + trackIndex = 0 + dataHashCode = -1045486664 + size = 248 + isKeyFrame = true + presentationTimeUs = 46584 +sample: + trackIndex = 0 + dataHashCode = -1465283679 + size = 260 + isKeyFrame = true + presentationTimeUs = 49167 +sample: + trackIndex = 0 + dataHashCode = 1840117006 + size = 254 + isKeyFrame = true + presentationTimeUs = 51875 +sample: + trackIndex = 0 + dataHashCode = -631848848 + size = 250 + isKeyFrame = true + presentationTimeUs = 54521 +sample: + trackIndex = 0 + dataHashCode = -1207491554 + size = 236 + isKeyFrame = true + presentationTimeUs = 57125 +sample: + trackIndex = 0 + dataHashCode = 838792456 + size = 258 + isKeyFrame = true + presentationTimeUs = 59584 +sample: + trackIndex = 0 + dataHashCode = -1131122284 + size = 264 + isKeyFrame = true + presentationTimeUs = 62271 +sample: + trackIndex = 0 + dataHashCode = -122326555 + size = 250 + isKeyFrame = true + presentationTimeUs = 65021 +sample: + trackIndex = 0 + dataHashCode = -1340323720 + size = 250 + isKeyFrame = true + presentationTimeUs = 67625 +sample: + trackIndex = 0 + dataHashCode = -1290952882 + size = 260 + isKeyFrame = true + presentationTimeUs = 70230 +sample: + trackIndex = 0 + dataHashCode = 2118216858 + size = 244 + isKeyFrame = true + presentationTimeUs = 72938 +sample: + trackIndex = 0 + dataHashCode = 879520231 + size = 252 + isKeyFrame = true + presentationTimeUs = 75480 +sample: + trackIndex = 0 + dataHashCode = -174892555 + size = 264 + isKeyFrame = true + presentationTimeUs = 78105 +sample: + trackIndex = 0 + dataHashCode = -555873771 + size = 252 + isKeyFrame = true + presentationTimeUs = 80855 +sample: + trackIndex = 0 + dataHashCode = -1479853263 + size = 256 + isKeyFrame = true + presentationTimeUs = 83480 +sample: + trackIndex = 0 + dataHashCode = -1068971504 + size = 250 + isKeyFrame = true + presentationTimeUs = 86146 +sample: + trackIndex = 0 + dataHashCode = -866214350 + size = 254 + isKeyFrame = true + presentationTimeUs = 88750 +sample: + trackIndex = 0 + dataHashCode = -2111034853 + size = 288 + isKeyFrame = true + presentationTimeUs = 91396 +sample: + trackIndex = 0 + dataHashCode = -1445430754 + size = 278 + isKeyFrame = true + presentationTimeUs = 94396 +sample: + trackIndex = 0 + dataHashCode = 1200468541 + size = 246 + isKeyFrame = true + presentationTimeUs = 97292 +sample: + trackIndex = 0 + dataHashCode = -1853596884 + size = 246 + isKeyFrame = true + presentationTimeUs = 99855 +sample: + trackIndex = 0 + dataHashCode = -1266372568 + size = 254 + isKeyFrame = true + presentationTimeUs = 102417 +sample: + trackIndex = 0 + dataHashCode = -212017561 + size = 248 + isKeyFrame = true + presentationTimeUs = 105063 +sample: + trackIndex = 0 + dataHashCode = -1464702479 + size = 8 + isKeyFrame = true + presentationTimeUs = 107646 +sample: + trackIndex = 1 + dataHashCode = -1830836678 + size = 1051 + isKeyFrame = false + presentationTimeUs = 500500 +sample: + trackIndex = 1 + dataHashCode = 1767407540 + size = 874 + isKeyFrame = false + presentationTimeUs = 467133 +sample: + trackIndex = 1 + dataHashCode = 918440283 + size = 781 + isKeyFrame = false + presentationTimeUs = 533866 +sample: + trackIndex = 1 + dataHashCode = -1408463661 + size = 4725 + isKeyFrame = false + presentationTimeUs = 700700 +sample: + trackIndex = 0 + dataHashCode = -2065 + size = 2 + isKeyFrame = true + presentationTimeUs = 107730 +sample: + trackIndex = 1 + dataHashCode = 1569455924 + size = 1022 + isKeyFrame = false + presentationTimeUs = 633966 +sample: + trackIndex = 1 + dataHashCode = -1723778407 + size = 790 + isKeyFrame = false + presentationTimeUs = 600600 +sample: + trackIndex = 1 + dataHashCode = 1578275472 + size = 610 + isKeyFrame = false + presentationTimeUs = 667333 +sample: + trackIndex = 1 + dataHashCode = 1989768395 + size = 2751 + isKeyFrame = false + presentationTimeUs = 834166 +sample: + trackIndex = 1 + dataHashCode = -1215674502 + size = 745 + isKeyFrame = false + presentationTimeUs = 767433 +sample: + trackIndex = 1 + dataHashCode = -814473606 + size = 621 + isKeyFrame = false + presentationTimeUs = 734066 +sample: + trackIndex = 1 + dataHashCode = 498370894 + size = 505 + isKeyFrame = false + presentationTimeUs = 800800 +sample: + trackIndex = 1 + dataHashCode = -1051506468 + size = 1268 + isKeyFrame = false + presentationTimeUs = 967633 +sample: + trackIndex = 1 + dataHashCode = -1025604144 + size = 880 + isKeyFrame = false + presentationTimeUs = 900900 +sample: + trackIndex = 1 + dataHashCode = -913586520 + size = 530 + isKeyFrame = false + presentationTimeUs = 867533 +sample: + trackIndex = 1 + dataHashCode = 1340459242 + size = 568 + isKeyFrame = false + presentationTimeUs = 934266 +released = true From 02fa8aa784b518f0ffad5c44da6eec1a94def4ee Mon Sep 17 00:00:00 2001 From: ibaker Date: Thu, 1 Dec 2022 14:48:29 +0000 Subject: [PATCH 039/183] Split SubripDecoder and ParsableByteArray tests In some cases we split a test method, and in other cases we just add line breaks to make the separation between arrange/act/assert more clear. PiperOrigin-RevId: 492182769 --- .../util/ParsableByteArrayTest.java | 85 ++++++++++++++----- .../text/subrip/SubripDecoderTest.java | 17 ++-- 2 files changed, 78 insertions(+), 24 deletions(-) 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 767aeeaf98..300c7a0dc5 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 @@ -332,6 +332,7 @@ public final class ParsableByteArrayTest { public void readLittleEndianLong() { 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); } @@ -339,6 +340,7 @@ public final class ParsableByteArrayTest { @Test public void readLittleEndianUnsignedInt() { ParsableByteArray byteArray = new ParsableByteArray(new byte[] {0x10, 0x00, 0x00, (byte) 0xFF}); + assertThat(byteArray.readLittleEndianUnsignedInt()).isEqualTo(0xFF000010L); assertThat(byteArray.getPosition()).isEqualTo(4); } @@ -346,6 +348,7 @@ public final class ParsableByteArrayTest { @Test public void readLittleEndianInt() { ParsableByteArray byteArray = new ParsableByteArray(new byte[] {0x01, 0x00, 0x00, (byte) 0xFF}); + assertThat(byteArray.readLittleEndianInt()).isEqualTo(0xFF000001); assertThat(byteArray.getPosition()).isEqualTo(4); } @@ -354,6 +357,7 @@ public final class ParsableByteArrayTest { public void readLittleEndianUnsignedInt24() { byte[] data = {0x01, 0x02, (byte) 0xFF}; ParsableByteArray byteArray = new ParsableByteArray(data); + assertThat(byteArray.readLittleEndianUnsignedInt24()).isEqualTo(0xFF0201); assertThat(byteArray.getPosition()).isEqualTo(3); } @@ -362,6 +366,7 @@ public final class ParsableByteArrayTest { public void readInt24Positive() { byte[] data = {0x01, 0x02, (byte) 0xFF}; ParsableByteArray byteArray = new ParsableByteArray(data); + assertThat(byteArray.readInt24()).isEqualTo(0x0102FF); assertThat(byteArray.getPosition()).isEqualTo(3); } @@ -370,6 +375,7 @@ public final class ParsableByteArrayTest { public void readInt24Negative() { byte[] data = {(byte) 0xFF, 0x02, (byte) 0x01}; ParsableByteArray byteArray = new ParsableByteArray(data); + assertThat(byteArray.readInt24()).isEqualTo(0xFFFF0201); assertThat(byteArray.getPosition()).isEqualTo(3); } @@ -378,6 +384,7 @@ public final class ParsableByteArrayTest { public void readLittleEndianUnsignedShort() { 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); @@ -388,6 +395,7 @@ public final class ParsableByteArrayTest { public void readLittleEndianShort() { 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); @@ -422,6 +430,7 @@ public final class ParsableByteArrayTest { (byte) 0x20, }; ParsableByteArray byteArray = new ParsableByteArray(data); + assertThat(byteArray.readString(data.length)).isEqualTo("ä ö ® π √ ± 谢 "); assertThat(byteArray.getPosition()).isEqualTo(data.length); } @@ -430,6 +439,7 @@ public final class ParsableByteArrayTest { public void readAsciiString() { byte[] data = new byte[] {'t', 'e', 's', 't'}; ParsableByteArray testArray = new ParsableByteArray(data); + assertThat(testArray.readString(data.length, forName("US-ASCII"))).isEqualTo("test"); assertThat(testArray.getPosition()).isEqualTo(data.length); } @@ -438,6 +448,7 @@ public final class ParsableByteArrayTest { public void readStringOutOfBoundsDoesNotMovePosition() { byte[] data = {(byte) 0xC3, (byte) 0xA4, (byte) 0x20}; ParsableByteArray byteArray = new ParsableByteArray(data); + try { byteArray.readString(data.length + 1); fail(); @@ -454,17 +465,22 @@ public final class ParsableByteArrayTest { } @Test - public void readNullTerminatedStringWithLengths() { + public void readNullTerminatedStringWithLengths_readLengthsMatchNullPositions() { 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"); assertThat(parser.getPosition()).isEqualTo(4); assertThat(parser.readNullTerminatedString(4)).isEqualTo("bar"); assertThat(parser.getPosition()).isEqualTo(8); assertThat(parser.readNullTerminatedString()).isNull(); - // Test with lengths that do not match NUL byte positions. - parser = new ParsableByteArray(bytes); + } + + @Test + public void readNullTerminatedStringWithLengths_readLengthsDontMatchNullPositions() { + byte[] bytes = new byte[] {'f', 'o', 'o', 0, 'b', 'a', 'r', 0}; + ParsableByteArray parser = new ParsableByteArray(bytes); + assertThat(parser.readNullTerminatedString(2)).isEqualTo("fo"); assertThat(parser.getPosition()).isEqualTo(2); assertThat(parser.readNullTerminatedString(2)).isEqualTo("o"); @@ -474,13 +490,23 @@ public final class ParsableByteArrayTest { assertThat(parser.readNullTerminatedString(1)).isEqualTo(""); assertThat(parser.getPosition()).isEqualTo(8); assertThat(parser.readNullTerminatedString()).isNull(); - // Test with limit at NUL - parser = new ParsableByteArray(bytes, 4); + } + + @Test + public void readNullTerminatedStringWithLengths_limitAtNull() { + byte[] bytes = new byte[] {'f', 'o', 'o', 0, 'b', 'a', 'r', 0}; + ParsableByteArray parser = new ParsableByteArray(bytes, /* limit= */ 4); + assertThat(parser.readNullTerminatedString(4)).isEqualTo("foo"); assertThat(parser.getPosition()).isEqualTo(4); assertThat(parser.readNullTerminatedString()).isNull(); - // Test with limit before NUL - parser = new ParsableByteArray(bytes, 3); + } + + @Test + public void readNullTerminatedStringWithLengths_limitBeforeNull() { + byte[] bytes = new byte[] {'f', 'o', 'o', 0, 'b', 'a', 'r', 0}; + ParsableByteArray parser = new ParsableByteArray(bytes, /* limit= */ 3); + assertThat(parser.readNullTerminatedString(3)).isEqualTo("foo"); assertThat(parser.getPosition()).isEqualTo(3); assertThat(parser.readNullTerminatedString()).isNull(); @@ -489,20 +515,30 @@ public final class ParsableByteArrayTest { @Test public void readNullTerminatedString() { 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"); assertThat(parser.getPosition()).isEqualTo(4); assertThat(parser.readNullTerminatedString()).isEqualTo("bar"); assertThat(parser.getPosition()).isEqualTo(8); assertThat(parser.readNullTerminatedString()).isNull(); - // Test with limit at NUL. - parser = new ParsableByteArray(bytes, 4); + } + + @Test + public void readNullTerminatedString_withLimitAtNull() { + byte[] bytes = new byte[] {'f', 'o', 'o', 0, 'b', 'a', 'r', 0}; + ParsableByteArray parser = new ParsableByteArray(bytes, /* limit= */ 4); + assertThat(parser.readNullTerminatedString()).isEqualTo("foo"); assertThat(parser.getPosition()).isEqualTo(4); assertThat(parser.readNullTerminatedString()).isNull(); - // Test with limit before NUL. - parser = new ParsableByteArray(bytes, 3); + } + + @Test + public void readNullTerminatedString_withLimitBeforeNull() { + byte[] bytes = new byte[] {'f', 'o', 'o', 0, 'b', 'a', 'r', 0}; + ParsableByteArray parser = new ParsableByteArray(bytes, /* limit= */ 3); + assertThat(parser.readNullTerminatedString()).isEqualTo("foo"); assertThat(parser.getPosition()).isEqualTo(3); assertThat(parser.readNullTerminatedString()).isNull(); @@ -512,6 +548,7 @@ public final class ParsableByteArrayTest { public void readNullTerminatedStringWithoutEndingNull() { 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"); assertThat(parser.readNullTerminatedString()).isNull(); @@ -520,30 +557,40 @@ public final class ParsableByteArrayTest { @Test public void readDelimiterTerminatedString() { byte[] bytes = new byte[] {'f', 'o', 'o', '*', 'b', 'a', 'r', '*'}; - // Test normal case. ParsableByteArray parser = new ParsableByteArray(bytes); + assertThat(parser.readDelimiterTerminatedString('*')).isEqualTo("foo"); assertThat(parser.getPosition()).isEqualTo(4); assertThat(parser.readDelimiterTerminatedString('*')).isEqualTo("bar"); assertThat(parser.getPosition()).isEqualTo(8); assertThat(parser.readDelimiterTerminatedString('*')).isNull(); + } + + @Test + public void readDelimiterTerminatedString_limitAtDelimiter() { + byte[] bytes = new byte[] {'f', 'o', 'o', '*', 'b', 'a', 'r', '*'}; + ParsableByteArray parser = new ParsableByteArray(bytes, /* limit= */ 4); - // Test with limit at delimiter. - parser = new ParsableByteArray(bytes, 4); assertThat(parser.readDelimiterTerminatedString('*')).isEqualTo("foo"); assertThat(parser.getPosition()).isEqualTo(4); assertThat(parser.readDelimiterTerminatedString('*')).isNull(); - // Test with limit before delimiter. - parser = new ParsableByteArray(bytes, 3); + } + + @Test + public void readDelimiterTerminatedString_limitBeforeDelimiter() { + byte[] bytes = new byte[] {'f', 'o', 'o', '*', 'b', 'a', 'r', '*'}; + ParsableByteArray parser = new ParsableByteArray(bytes, /* limit= */ 3); + assertThat(parser.readDelimiterTerminatedString('*')).isEqualTo("foo"); assertThat(parser.getPosition()).isEqualTo(3); assertThat(parser.readDelimiterTerminatedString('*')).isNull(); } @Test - public void readDelimiterTerminatedStringWithoutEndingDelimiter() { + public void readDelimiterTerminatedStringW_noDelimiter() { byte[] bytes = new byte[] {'f', 'o', 'o', '*', 'b', 'a', 'r'}; ParsableByteArray parser = new ParsableByteArray(bytes); + assertThat(parser.readDelimiterTerminatedString('*')).isEqualTo("foo"); assertThat(parser.readDelimiterTerminatedString('*')).isEqualTo("bar"); assertThat(parser.readDelimiterTerminatedString('*')).isNull(); diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/text/subrip/SubripDecoderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/text/subrip/SubripDecoderTest.java index 2707db0ff3..828a6b7f7c 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/text/subrip/SubripDecoderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/text/subrip/SubripDecoderTest.java @@ -50,6 +50,7 @@ public final class SubripDecoderTest { public void decodeEmpty() throws IOException { SubripDecoder decoder = new SubripDecoder(); byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), EMPTY_FILE); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(0); @@ -60,6 +61,7 @@ public final class SubripDecoderTest { public void decodeTypical() throws IOException { SubripDecoder decoder = new SubripDecoder(); byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_FILE); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(6); @@ -74,6 +76,7 @@ public final class SubripDecoderTest { byte[] bytes = TestUtil.getByteArray( ApplicationProvider.getApplicationContext(), TYPICAL_WITH_BYTE_ORDER_MARK); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(6); @@ -88,6 +91,7 @@ public final class SubripDecoderTest { byte[] bytes = TestUtil.getByteArray( ApplicationProvider.getApplicationContext(), TYPICAL_EXTRA_BLANK_LINE); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(6); @@ -103,6 +107,7 @@ public final class SubripDecoderTest { byte[] bytes = TestUtil.getByteArray( ApplicationProvider.getApplicationContext(), TYPICAL_MISSING_TIMECODE); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -117,6 +122,7 @@ public final class SubripDecoderTest { byte[] bytes = TestUtil.getByteArray( ApplicationProvider.getApplicationContext(), TYPICAL_MISSING_SEQUENCE); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -131,6 +137,7 @@ public final class SubripDecoderTest { byte[] bytes = TestUtil.getByteArray( ApplicationProvider.getApplicationContext(), TYPICAL_NEGATIVE_TIMESTAMPS); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(2); @@ -143,6 +150,7 @@ public final class SubripDecoderTest { SubripDecoder decoder = new SubripDecoder(); byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_UNEXPECTED_END); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(4); @@ -155,6 +163,7 @@ public final class SubripDecoderTest { SubripDecoder decoder = new SubripDecoder(); byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_UTF16LE); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(6); @@ -168,6 +177,7 @@ public final class SubripDecoderTest { SubripDecoder decoder = new SubripDecoder(); byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_UTF16BE); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(6); @@ -181,23 +191,19 @@ public final class SubripDecoderTest { SubripDecoder decoder = new SubripDecoder(); byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_WITH_TAGS); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getCues(subtitle.getEventTime(0)).get(0).text.toString()) .isEqualTo("This is the first subtitle."); - assertThat(subtitle.getCues(subtitle.getEventTime(2)).get(0).text.toString()) .isEqualTo("This is the second subtitle.\nSecond subtitle with second line."); - assertThat(subtitle.getCues(subtitle.getEventTime(4)).get(0).text.toString()) .isEqualTo("This is the third subtitle."); - assertThat(subtitle.getCues(subtitle.getEventTime(6)).get(0).text.toString()) .isEqualTo("This { \\an2} is not a valid tag due to the space after the opening bracket."); - assertThat(subtitle.getCues(subtitle.getEventTime(8)).get(0).text.toString()) .isEqualTo("This is the fifth subtitle with multiple valid tags."); - assertAlignmentCue(subtitle, 10, Cue.ANCHOR_TYPE_END, Cue.ANCHOR_TYPE_START); // {/an1} assertAlignmentCue(subtitle, 12, Cue.ANCHOR_TYPE_END, Cue.ANCHOR_TYPE_MIDDLE); // {/an2} assertAlignmentCue(subtitle, 14, Cue.ANCHOR_TYPE_END, Cue.ANCHOR_TYPE_END); // {/an3} @@ -215,6 +221,7 @@ public final class SubripDecoderTest { byte[] bytes = TestUtil.getByteArray( ApplicationProvider.getApplicationContext(), TYPICAL_NO_HOURS_AND_MILLIS); + Subtitle subtitle = decoder.decode(bytes, bytes.length, false); assertThat(subtitle.getEventTimeCount()).isEqualTo(6); From 16ea364478cc01472cfdf0342d1268882c35c873 Mon Sep 17 00:00:00 2001 From: samrobinson Date: Thu, 1 Dec 2022 15:56:34 +0000 Subject: [PATCH 040/183] Merge feedXFromInput and feedXFromSilence in ATSP. PiperOrigin-RevId: 492195931 --- .../AudioTranscodingSamplePipeline.java | 70 +++++-------------- 1 file changed, 17 insertions(+), 53 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java index e6ba26a882..4887e38ef6 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java @@ -32,6 +32,7 @@ import com.google.android.exoplayer2.util.Util; import com.google.common.collect.ImmutableList; import java.nio.ByteBuffer; import java.util.List; +import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.dataflow.qual.Pure; /** @@ -174,16 +175,10 @@ import org.checkerframework.dataflow.qual.Pure; @Override protected boolean processDataUpToMuxer() throws TransformationException { if (!audioProcessingPipeline.isOperational()) { - return silentAudioGenerator == null ? feedEncoderFromInput() : feedEncoderFromSilence(); + return feedEncoderFromInput(); } - if (feedEncoderFromProcessingPipeline()) { - return true; - } - - return silentAudioGenerator == null - ? feedProcessingPipelineFromInput() - : feedProcessingPipelineFromSilence(); + return feedEncoderFromProcessingPipeline() || feedProcessingPipelineFromInput(); } @Override @@ -220,17 +215,19 @@ import org.checkerframework.dataflow.qual.Pure; * @return Whether it may be possible to feed more data immediately by calling this method again. */ private boolean feedEncoderFromInput() throws TransformationException { - if (!hasPendingInputBuffer || !encoder.maybeDequeueInputBuffer(encoderInputBuffer)) { + if ((!isInputSilent() && !hasPendingInputBuffer) + || !encoder.maybeDequeueInputBuffer(encoderInputBuffer)) { return false; } - if (inputBuffer.isEndOfStream()) { + if (isInputSilent() ? silentAudioGenerator.isEnded() : inputBuffer.isEndOfStream()) { queueEndOfStreamToEncoder(); hasPendingInputBuffer = false; return false; } - ByteBuffer inputData = checkNotNull(inputBuffer.data); + ByteBuffer inputData = + isInputSilent() ? silentAudioGenerator.getBuffer() : checkNotNull(inputBuffer.data); feedEncoder(inputData); if (!inputData.hasRemaining()) { hasPendingInputBuffer = false; @@ -267,18 +264,19 @@ import org.checkerframework.dataflow.qual.Pure; * @return Whether it may be possible to feed more data immediately by calling this method again. */ private boolean feedProcessingPipelineFromInput() { - if (!hasPendingInputBuffer) { + if (!isInputSilent() && !hasPendingInputBuffer) { return false; } - if (inputBuffer.isEndOfStream()) { + if (isInputSilent() ? silentAudioGenerator.isEnded() : inputBuffer.isEndOfStream()) { audioProcessingPipeline.queueEndOfStream(); hasPendingInputBuffer = false; return false; } checkState(!audioProcessingPipeline.isEnded()); - ByteBuffer inputData = checkNotNull(inputBuffer.data); + ByteBuffer inputData = + isInputSilent() ? silentAudioGenerator.getBuffer() : checkNotNull(inputBuffer.data); audioProcessingPipeline.queueInput(inputData); if (inputData.hasRemaining()) { return false; @@ -287,45 +285,6 @@ import org.checkerframework.dataflow.qual.Pure; return true; } - /** - * Attempts to pass silent audio to the encoder. - * - * @return Whether it may be possible to feed more data immediately by calling this method again. - */ - private boolean feedEncoderFromSilence() throws TransformationException { - checkNotNull(silentAudioGenerator); - if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) { - return false; - } - - if (silentAudioGenerator.isEnded()) { - queueEndOfStreamToEncoder(); - return false; - } - - ByteBuffer silence = silentAudioGenerator.getBuffer(); - feedEncoder(silence); - return true; - } - - /** - * Attempts to feed silent audio to the {@link AudioProcessingPipeline}. - * - * @return Whether it may be possible to feed more data immediately by calling this method again. - */ - private boolean feedProcessingPipelineFromSilence() { - checkNotNull(silentAudioGenerator); - if (silentAudioGenerator.isEnded()) { - audioProcessingPipeline.queueEndOfStream(); - return false; - } - checkState(!audioProcessingPipeline.isEnded()); - - ByteBuffer silence = silentAudioGenerator.getBuffer(); - audioProcessingPipeline.queueInput(silence); - return !silence.hasRemaining(); - } - /** * Feeds as much data as possible between the current position and limit of the specified {@link * ByteBuffer} to the encoder, and advances its position by the number of bytes fed. @@ -400,4 +359,9 @@ import org.checkerframework.dataflow.qual.Pure; } nextEncoderInputBufferTimeUs += bufferDurationUs; } + + @EnsuresNonNullIf(expression = "silentAudioGenerator", result = true) + private boolean isInputSilent() { + return silentAudioGenerator != null; + } } From c42fc6f33fb36470951cdee5ec73ad840aea991e Mon Sep 17 00:00:00 2001 From: kimvde Date: Fri, 2 Dec 2022 07:36:47 +0000 Subject: [PATCH 041/183] Make sure that the sample pipeline data is processed regularly. This is necessary to move video decoding to the AssetLoader. Otherwise, if the decoder max pending frame count is reached, the AssetLoader will stop queuing frames to the pipeline, and process data will not be called anymore. PiperOrigin-RevId: 492392621 --- .../transformer/TransformerInternal.java | 33 ++-- .../mkv/sample_with_srt.mkv.dump | 144 ++++++++-------- .../mp4/sample.mp4.48000hz.dump | 156 +++++++++--------- .../transformerdumps/mp4/sample.mp4.dump | 82 ++++----- .../mp4/sample_sef_slow_motion.mp4.dump | 144 ++++++++-------- ...sing_timestamps_320w_240h.mp4.clipped.dump | 120 +++++++------- 6 files changed, 338 insertions(+), 341 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java index 5dad73f446..d64f38f1ce 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java @@ -21,7 +21,6 @@ import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STA import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE; import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_WAITING_FOR_AVAILABILITY; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; -import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; import static java.lang.Math.min; import static java.lang.annotation.ElementType.TYPE_USE; @@ -91,7 +90,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private static final int MSG_DRAIN_PIPELINES = 4; private static final int MSG_END = 5; - private static final int DRAIN_PIPELINES_DELAY_MS = 10; + private static final int DRAIN_PIPELINES_DELAY_MS = 50; private final Context context; private final TransformationRequest transformationRequest; @@ -223,13 +222,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; startInternal(); break; case MSG_REGISTER_SAMPLE_PIPELINE: - samplePipelines.add((SamplePipeline) msg.obj); + registerSamplePipelineInternal((SamplePipeline) msg.obj); break; case MSG_DEQUEUE_INPUT: dequeueInputInternal(/* samplePipelineIndex= */ msg.arg1); break; case MSG_QUEUE_INPUT: - queueInputInternal(/* samplePipelineIndex= */ msg.arg1); + samplePipelines.get(/* samplePipelineIndex= */ msg.arg1).queueInputBuffer(); break; case MSG_DRAIN_PIPELINES: drainPipelinesInternal(); @@ -254,12 +253,19 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; exoPlayerAssetLoader.start(); } + private void registerSamplePipelineInternal(SamplePipeline samplePipeline) { + samplePipelines.add(samplePipeline); + if (!isDrainingPipelines) { + // Make sure pipelines are drained regularly to prevent them from getting stuck. + internalHandler.sendEmptyMessageDelayed(MSG_DRAIN_PIPELINES, DRAIN_PIPELINES_DELAY_MS); + isDrainingPipelines = true; + } + } + private void dequeueInputInternal(int samplePipelineIndex) throws TransformationException { SamplePipeline samplePipeline = samplePipelines.get(samplePipelineIndex); - // The sample pipeline is drained before dequeuing input. It can't be done before queuing - // input because, if the pipeline is full, dequeuing input would forever return a null buffer. - // Draining the pipeline at regular intervals would be inefficient because a low interval could - // result in many no-op operations, and a high interval could slow down data queuing. + // The sample pipeline is drained before dequeuing input to maximise the chances of having an + // input buffer to dequeue. while (samplePipeline.processData()) {} pendingInputBuffer = samplePipeline.dequeueInputBuffer(); dequeueBufferConditionVariable.open(); @@ -269,15 +275,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } } - private void queueInputInternal(int samplePipelineIndex) throws TransformationException { - DecoderInputBuffer pendingInputBuffer = checkStateNotNull(this.pendingInputBuffer); - samplePipelines.get(samplePipelineIndex).queueInputBuffer(); - if (pendingInputBuffer.isEndOfStream() && !isDrainingPipelines) { - internalHandler.sendEmptyMessageDelayed(MSG_DRAIN_PIPELINES, DRAIN_PIPELINES_DELAY_MS); - isDrainingPipelines = true; - } - } - private void drainPipelinesInternal() throws TransformationException { for (int i = 0; i < samplePipelines.size(); i++) { while (samplePipelines.get(i).processData()) {} @@ -630,7 +627,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; return null; } // TODO(b/252537210): Reduce the number of thread hops (for example by adding a queue at the - // start of thesample pipelines). Having 2 thread hops per sample (one for dequeuing and + // start of the sample pipelines). Having 2 thread hops per sample (one for dequeuing and // one for queuing) makes transmuxing slower than it used to be. internalHandler .obtainMessage(MSG_DEQUEUE_INPUT, samplePipelineIndex, /* unused */ 0) diff --git a/testdata/src/test/assets/transformerdumps/mkv/sample_with_srt.mkv.dump b/testdata/src/test/assets/transformerdumps/mkv/sample_with_srt.mkv.dump index 4709eeda17..5789404820 100644 --- a/testdata/src/test/assets/transformerdumps/mkv/sample_with_srt.mkv.dump +++ b/testdata/src/test/assets/transformerdumps/mkv/sample_with_srt.mkv.dump @@ -14,6 +14,72 @@ format 1: initializationData: data = length 30, hash F6F3D010 data = length 10, hash 7A0D0F2B +sample: + trackIndex = 0 + dataHashCode = 555688582 + size = 416 + isKeyFrame = true + presentationTimeUs = 0 +sample: + trackIndex = 0 + dataHashCode = 2000837254 + size = 418 + isKeyFrame = true + presentationTimeUs = 4717 +sample: + trackIndex = 0 + dataHashCode = -1593942879 + size = 418 + isKeyFrame = true + presentationTimeUs = 9456 +sample: + trackIndex = 0 + dataHashCode = 587837542 + size = 418 + isKeyFrame = true + presentationTimeUs = 14196 +sample: + trackIndex = 0 + dataHashCode = -1836423877 + size = 418 + isKeyFrame = true + presentationTimeUs = 18935 +sample: + trackIndex = 0 + dataHashCode = 874705099 + size = 418 + isKeyFrame = true + presentationTimeUs = 23674 +sample: + trackIndex = 0 + dataHashCode = -269206181 + size = 418 + isKeyFrame = true + presentationTimeUs = 28413 +sample: + trackIndex = 0 + dataHashCode = -58682425 + size = 418 + isKeyFrame = true + presentationTimeUs = 33152 +sample: + trackIndex = 0 + dataHashCode = -859796970 + size = 418 + isKeyFrame = true + presentationTimeUs = 37892 +sample: + trackIndex = 0 + dataHashCode = 711911523 + size = 418 + isKeyFrame = true + presentationTimeUs = 42631 +sample: + trackIndex = 0 + dataHashCode = -694513071 + size = 418 + isKeyFrame = true + presentationTimeUs = 47370 sample: trackIndex = 1 dataHashCode = -252482306 @@ -104,72 +170,6 @@ sample: size = 5525 isKeyFrame = false presentationTimeUs = 567000 -sample: - trackIndex = 0 - dataHashCode = 555688582 - size = 416 - isKeyFrame = true - presentationTimeUs = 0 -sample: - trackIndex = 0 - dataHashCode = 2000837254 - size = 418 - isKeyFrame = true - presentationTimeUs = 4717 -sample: - trackIndex = 0 - dataHashCode = -1593942879 - size = 418 - isKeyFrame = true - presentationTimeUs = 9456 -sample: - trackIndex = 0 - dataHashCode = 587837542 - size = 418 - isKeyFrame = true - presentationTimeUs = 14196 -sample: - trackIndex = 0 - dataHashCode = -1836423877 - size = 418 - isKeyFrame = true - presentationTimeUs = 18935 -sample: - trackIndex = 0 - dataHashCode = 874705099 - size = 418 - isKeyFrame = true - presentationTimeUs = 23674 -sample: - trackIndex = 0 - dataHashCode = -269206181 - size = 418 - isKeyFrame = true - presentationTimeUs = 28413 -sample: - trackIndex = 0 - dataHashCode = -58682425 - size = 418 - isKeyFrame = true - presentationTimeUs = 33152 -sample: - trackIndex = 0 - dataHashCode = -859796970 - size = 418 - isKeyFrame = true - presentationTimeUs = 37892 -sample: - trackIndex = 0 - dataHashCode = 711911523 - size = 418 - isKeyFrame = true - presentationTimeUs = 42631 -sample: - trackIndex = 0 - dataHashCode = -694513071 - size = 418 - isKeyFrame = true - presentationTimeUs = 47370 sample: trackIndex = 0 dataHashCode = -1124371059 @@ -200,6 +200,12 @@ sample: size = 418 isKeyFrame = true presentationTimeUs = 71066 +sample: + trackIndex = 1 + dataHashCode = -637074022 + size = 1082 + isKeyFrame = false + presentationTimeUs = 500000 sample: trackIndex = 0 dataHashCode = 1297086772 @@ -278,12 +284,6 @@ sample: size = 418 isKeyFrame = true presentationTimeUs = 132676 -sample: - trackIndex = 1 - dataHashCode = -637074022 - size = 1082 - isKeyFrame = false - presentationTimeUs = 500000 sample: trackIndex = 1 dataHashCode = -1824027029 diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.48000hz.dump b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.48000hz.dump index b11eb46460..80419c61a0 100644 --- a/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.48000hz.dump +++ b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.48000hz.dump @@ -14,6 +14,78 @@ format 1: initializationData: data = length 29, hash 4746B5D9 data = length 10, hash 7A0D0F2B +sample: + trackIndex = 0 + dataHashCode = 1868041800 + size = 22 + isKeyFrame = true + presentationTimeUs = 0 +sample: + trackIndex = 0 + dataHashCode = 1552866193 + size = 8 + isKeyFrame = true + presentationTimeUs = 230 +sample: + trackIndex = 0 + dataHashCode = 701848493 + size = 160 + isKeyFrame = true + presentationTimeUs = 313 +sample: + trackIndex = 0 + dataHashCode = 2000505720 + size = 206 + isKeyFrame = true + presentationTimeUs = 1980 +sample: + trackIndex = 0 + dataHashCode = 57276327 + size = 222 + isKeyFrame = true + presentationTimeUs = 4125 +sample: + trackIndex = 0 + dataHashCode = 382237408 + size = 228 + isKeyFrame = true + presentationTimeUs = 6438 +sample: + trackIndex = 0 + dataHashCode = 795308374 + size = 228 + isKeyFrame = true + presentationTimeUs = 8813 +sample: + trackIndex = 0 + dataHashCode = 356270426 + size = 224 + isKeyFrame = true + presentationTimeUs = 11188 +sample: + trackIndex = 0 + dataHashCode = 963641614 + size = 244 + isKeyFrame = true + presentationTimeUs = 13521 +sample: + trackIndex = 0 + dataHashCode = 2045272193 + size = 234 + isKeyFrame = true + presentationTimeUs = 16063 +sample: + trackIndex = 0 + dataHashCode = -251933090 + size = 228 + isKeyFrame = true + presentationTimeUs = 18500 +sample: + trackIndex = 0 + dataHashCode = -329315280 + size = 234 + isKeyFrame = true + presentationTimeUs = 20875 sample: trackIndex = 1 dataHashCode = -770308242 @@ -104,78 +176,6 @@ sample: size = 5450 isKeyFrame = false presentationTimeUs = 567233 -sample: - trackIndex = 0 - dataHashCode = 1868041800 - size = 22 - isKeyFrame = true - presentationTimeUs = 0 -sample: - trackIndex = 0 - dataHashCode = 1552866193 - size = 8 - isKeyFrame = true - presentationTimeUs = 230 -sample: - trackIndex = 0 - dataHashCode = 701848493 - size = 160 - isKeyFrame = true - presentationTimeUs = 313 -sample: - trackIndex = 0 - dataHashCode = 2000505720 - size = 206 - isKeyFrame = true - presentationTimeUs = 1980 -sample: - trackIndex = 0 - dataHashCode = 57276327 - size = 222 - isKeyFrame = true - presentationTimeUs = 4125 -sample: - trackIndex = 0 - dataHashCode = 382237408 - size = 228 - isKeyFrame = true - presentationTimeUs = 6438 -sample: - trackIndex = 0 - dataHashCode = 795308374 - size = 228 - isKeyFrame = true - presentationTimeUs = 8813 -sample: - trackIndex = 0 - dataHashCode = 356270426 - size = 224 - isKeyFrame = true - presentationTimeUs = 11188 -sample: - trackIndex = 0 - dataHashCode = 963641614 - size = 244 - isKeyFrame = true - presentationTimeUs = 13521 -sample: - trackIndex = 0 - dataHashCode = 2045272193 - size = 234 - isKeyFrame = true - presentationTimeUs = 16063 -sample: - trackIndex = 0 - dataHashCode = -251933090 - size = 228 - isKeyFrame = true - presentationTimeUs = 18500 -sample: - trackIndex = 0 - dataHashCode = -329315280 - size = 234 - isKeyFrame = true - presentationTimeUs = 20875 sample: trackIndex = 0 dataHashCode = -1536715689 @@ -284,6 +284,12 @@ sample: size = 250 isKeyFrame = true presentationTimeUs = 67625 +sample: + trackIndex = 1 + dataHashCode = -1830836678 + size = 1051 + isKeyFrame = false + presentationTimeUs = 500500 sample: trackIndex = 0 dataHashCode = -1290952882 @@ -374,12 +380,6 @@ sample: size = 8 isKeyFrame = true presentationTimeUs = 107646 -sample: - trackIndex = 1 - dataHashCode = -1830836678 - size = 1051 - isKeyFrame = false - presentationTimeUs = 500500 sample: trackIndex = 1 dataHashCode = 1767407540 diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.dump b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.dump index 2ee74557d5..19def158f3 100644 --- a/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.dump +++ b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.dump @@ -21,6 +21,12 @@ format 1: initializationData: data = length 29, hash 4746B5D9 data = length 10, hash 7A0D0F2B +sample: + trackIndex = 0 + dataHashCode = 1205768497 + size = 23 + isKeyFrame = true + presentationTimeUs = 44000 sample: trackIndex = 1 dataHashCode = -770308242 @@ -111,12 +117,6 @@ sample: size = 5450 isKeyFrame = false presentationTimeUs = 567233 -sample: - trackIndex = 0 - dataHashCode = 1205768497 - size = 23 - isKeyFrame = true - presentationTimeUs = 44000 sample: trackIndex = 0 dataHashCode = 837571078 @@ -129,6 +129,12 @@ sample: size = 148 isKeyFrame = true presentationTimeUs = 90439 +sample: + trackIndex = 1 + dataHashCode = -1830836678 + size = 1051 + isKeyFrame = false + presentationTimeUs = 500500 sample: trackIndex = 0 dataHashCode = -822987359 @@ -238,17 +244,41 @@ sample: isKeyFrame = true presentationTimeUs = 508399 sample: - trackIndex = 1 - dataHashCode = -1830836678 - size = 1051 - isKeyFrame = false - presentationTimeUs = 500500 + trackIndex = 0 + dataHashCode = 1675188486 + size = 228 + isKeyFrame = true + presentationTimeUs = 531619 +sample: + trackIndex = 0 + dataHashCode = 888567545 + size = 238 + isKeyFrame = true + presentationTimeUs = 554839 +sample: + trackIndex = 0 + dataHashCode = -439631803 + size = 234 + isKeyFrame = true + presentationTimeUs = 578058 +sample: + trackIndex = 0 + dataHashCode = 1606694497 + size = 231 + isKeyFrame = true + presentationTimeUs = 601278 sample: trackIndex = 1 dataHashCode = 1767407540 size = 874 isKeyFrame = false presentationTimeUs = 467133 +sample: + trackIndex = 0 + dataHashCode = 1747388653 + size = 217 + isKeyFrame = true + presentationTimeUs = 624498 sample: trackIndex = 1 dataHashCode = 918440283 @@ -327,36 +357,6 @@ sample: size = 568 isKeyFrame = false presentationTimeUs = 934266 -sample: - trackIndex = 0 - dataHashCode = 1675188486 - size = 228 - isKeyFrame = true - presentationTimeUs = 531619 -sample: - trackIndex = 0 - dataHashCode = 888567545 - size = 238 - isKeyFrame = true - presentationTimeUs = 554839 -sample: - trackIndex = 0 - dataHashCode = -439631803 - size = 234 - isKeyFrame = true - presentationTimeUs = 578058 -sample: - trackIndex = 0 - dataHashCode = 1606694497 - size = 231 - isKeyFrame = true - presentationTimeUs = 601278 -sample: - trackIndex = 0 - dataHashCode = 1747388653 - size = 217 - isKeyFrame = true - presentationTimeUs = 624498 sample: trackIndex = 0 dataHashCode = -734560004 diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample_sef_slow_motion.mp4.dump b/testdata/src/test/assets/transformerdumps/mp4/sample_sef_slow_motion.mp4.dump index fc0a46dd7d..bdd2160cc1 100644 --- a/testdata/src/test/assets/transformerdumps/mp4/sample_sef_slow_motion.mp4.dump +++ b/testdata/src/test/assets/transformerdumps/mp4/sample_sef_slow_motion.mp4.dump @@ -15,6 +15,78 @@ format 1: initializationData: data = length 33, hash D3FB879D data = length 10, hash 7A0D0F2B +sample: + trackIndex = 0 + dataHashCode = -212376212 + size = 20 + isKeyFrame = true + presentationTimeUs = 0 +sample: + trackIndex = 0 + dataHashCode = -1948569090 + size = 72 + isKeyFrame = true + presentationTimeUs = 417 +sample: + trackIndex = 0 + dataHashCode = -1316750072 + size = 84 + isKeyFrame = true + presentationTimeUs = 1917 +sample: + trackIndex = 0 + dataHashCode = 1016428949 + size = 88 + isKeyFrame = true + presentationTimeUs = 3667 +sample: + trackIndex = 0 + dataHashCode = -1127325245 + size = 96 + isKeyFrame = true + presentationTimeUs = 5500 +sample: + trackIndex = 0 + dataHashCode = 1148147726 + size = 92 + isKeyFrame = true + presentationTimeUs = 7500 +sample: + trackIndex = 0 + dataHashCode = -2125685540 + size = 76 + isKeyFrame = true + presentationTimeUs = 9417 +sample: + trackIndex = 0 + dataHashCode = 473329679 + size = 24 + isKeyFrame = true + presentationTimeUs = 11000 +sample: + trackIndex = 0 + dataHashCode = 240990900 + size = 176 + isKeyFrame = true + presentationTimeUs = 11500 +sample: + trackIndex = 0 + dataHashCode = 777637182 + size = 196 + isKeyFrame = true + presentationTimeUs = 15167 +sample: + trackIndex = 0 + dataHashCode = 1872106264 + size = 180 + isKeyFrame = true + presentationTimeUs = 19250 +sample: + trackIndex = 0 + dataHashCode = -1520711499 + size = 140 + isKeyFrame = true + presentationTimeUs = 23000 sample: trackIndex = 1 dataHashCode = 1949079733 @@ -123,78 +195,6 @@ sample: size = 1109 isKeyFrame = false presentationTimeUs = 600750 -sample: - trackIndex = 0 - dataHashCode = -212376212 - size = 20 - isKeyFrame = true - presentationTimeUs = 0 -sample: - trackIndex = 0 - dataHashCode = -1948569090 - size = 72 - isKeyFrame = true - presentationTimeUs = 417 -sample: - trackIndex = 0 - dataHashCode = -1316750072 - size = 84 - isKeyFrame = true - presentationTimeUs = 1917 -sample: - trackIndex = 0 - dataHashCode = 1016428949 - size = 88 - isKeyFrame = true - presentationTimeUs = 3667 -sample: - trackIndex = 0 - dataHashCode = -1127325245 - size = 96 - isKeyFrame = true - presentationTimeUs = 5500 -sample: - trackIndex = 0 - dataHashCode = 1148147726 - size = 92 - isKeyFrame = true - presentationTimeUs = 7500 -sample: - trackIndex = 0 - dataHashCode = -2125685540 - size = 76 - isKeyFrame = true - presentationTimeUs = 9417 -sample: - trackIndex = 0 - dataHashCode = 473329679 - size = 24 - isKeyFrame = true - presentationTimeUs = 11000 -sample: - trackIndex = 0 - dataHashCode = 240990900 - size = 176 - isKeyFrame = true - presentationTimeUs = 11500 -sample: - trackIndex = 0 - dataHashCode = 777637182 - size = 196 - isKeyFrame = true - presentationTimeUs = 15167 -sample: - trackIndex = 0 - dataHashCode = 1872106264 - size = 180 - isKeyFrame = true - presentationTimeUs = 19250 -sample: - trackIndex = 0 - dataHashCode = -1520711499 - size = 140 - isKeyFrame = true - presentationTimeUs = 23000 sample: trackIndex = 0 dataHashCode = 1580199067 diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample_with_increasing_timestamps_320w_240h.mp4.clipped.dump b/testdata/src/test/assets/transformerdumps/mp4/sample_with_increasing_timestamps_320w_240h.mp4.clipped.dump index f37630c1cd..ec0af92443 100644 --- a/testdata/src/test/assets/transformerdumps/mp4/sample_with_increasing_timestamps_320w_240h.mp4.clipped.dump +++ b/testdata/src/test/assets/transformerdumps/mp4/sample_with_increasing_timestamps_320w_240h.mp4.clipped.dump @@ -27,6 +27,12 @@ format 1: initializationData: data = length 31, hash 4B108214 data = length 9, hash FBA158BB +sample: + trackIndex = 0 + dataHashCode = 620415738 + size = 508 + isKeyFrame = true + presentationTimeUs = 7020 sample: trackIndex = 1 dataHashCode = 983000500 @@ -219,18 +225,18 @@ sample: size = 151 isKeyFrame = false presentationTimeUs = 516666 -sample: - trackIndex = 0 - dataHashCode = 620415738 - size = 508 - isKeyFrame = true - presentationTimeUs = 7020 sample: trackIndex = 0 dataHashCode = 33931768 size = 504 isKeyFrame = true presentationTimeUs = 28354 +sample: + trackIndex = 1 + dataHashCode = 264118578 + size = 2235 + isKeyFrame = false + presentationTimeUs = 533333 sample: trackIndex = 0 dataHashCode = 800699278 @@ -370,17 +376,23 @@ sample: isKeyFrame = true presentationTimeUs = 519020 sample: - trackIndex = 1 - dataHashCode = 264118578 - size = 2235 - isKeyFrame = false - presentationTimeUs = 533333 + trackIndex = 0 + dataHashCode = 204379389 + size = 504 + isKeyFrame = true + presentationTimeUs = 540354 sample: trackIndex = 1 dataHashCode = 64254117 size = 164 isKeyFrame = false presentationTimeUs = 550000 +sample: + trackIndex = 0 + dataHashCode = 694913274 + size = 508 + isKeyFrame = true + presentationTimeUs = 561687 sample: trackIndex = 1 dataHashCode = -1000078879 @@ -556,23 +568,29 @@ sample: isKeyFrame = false presentationTimeUs = 1033333 sample: - trackIndex = 0 - dataHashCode = 204379389 - size = 504 - isKeyFrame = true - presentationTimeUs = 540354 + trackIndex = 1 + dataHashCode = 65238903 + size = 163 + isKeyFrame = false + presentationTimeUs = 1050000 sample: - trackIndex = 0 - dataHashCode = 694913274 - size = 508 - isKeyFrame = true - presentationTimeUs = 561687 + trackIndex = 1 + dataHashCode = 1720840922 + size = 2043 + isKeyFrame = false + presentationTimeUs = 1066666 sample: trackIndex = 0 dataHashCode = 289018778 size = 513 isKeyFrame = true presentationTimeUs = 583020 +sample: + trackIndex = 1 + dataHashCode = -1006231050 + size = 178 + isKeyFrame = false + presentationTimeUs = 1083333 sample: trackIndex = 0 dataHashCode = -693167785 @@ -700,29 +718,35 @@ sample: isKeyFrame = true presentationTimeUs = 1031020 sample: - trackIndex = 1 - dataHashCode = 65238903 - size = 163 - isKeyFrame = false - presentationTimeUs = 1050000 + trackIndex = 0 + dataHashCode = -320096195 + size = 509 + isKeyFrame = true + presentationTimeUs = 1052354 sample: - trackIndex = 1 - dataHashCode = 1720840922 - size = 2043 - isKeyFrame = false - presentationTimeUs = 1066666 + trackIndex = 0 + dataHashCode = -744850549 + size = 511 + isKeyFrame = true + presentationTimeUs = 1073687 sample: - trackIndex = 1 - dataHashCode = -1006231050 - size = 178 - isKeyFrame = false - presentationTimeUs = 1083333 + trackIndex = 0 + dataHashCode = 1457899387 + size = 505 + isKeyFrame = true + presentationTimeUs = 1095020 sample: trackIndex = 1 dataHashCode = 1742965952 size = 2022 isKeyFrame = false presentationTimeUs = 1100000 +sample: + trackIndex = 0 + dataHashCode = 168118808 + size = 519 + isKeyFrame = true + presentationTimeUs = 1116354 sample: trackIndex = 1 dataHashCode = -971065365 @@ -861,30 +885,6 @@ sample: size = 119 isKeyFrame = false presentationTimeUs = 1483333 -sample: - trackIndex = 0 - dataHashCode = -320096195 - size = 509 - isKeyFrame = true - presentationTimeUs = 1052354 -sample: - trackIndex = 0 - dataHashCode = -744850549 - size = 511 - isKeyFrame = true - presentationTimeUs = 1073687 -sample: - trackIndex = 0 - dataHashCode = 1457899387 - size = 505 - isKeyFrame = true - presentationTimeUs = 1095020 -sample: - trackIndex = 0 - dataHashCode = 168118808 - size = 519 - isKeyFrame = true - presentationTimeUs = 1116354 sample: trackIndex = 0 dataHashCode = 896298799 From 08f6fe172732f8a3327746f249888368c39265bc Mon Sep 17 00:00:00 2001 From: michaelkatz Date: Fri, 2 Dec 2022 13:14:33 +0000 Subject: [PATCH 042/183] Removed ExoPlayer specific states from SimpleBasePlayer PiperOrigin-RevId: 492443147 --- .../android/exoplayer2/SimpleBasePlayer.java | 50 ------------------- .../exoplayer2/SimpleBasePlayerTest.java | 19 ++----- 2 files changed, 5 insertions(+), 64 deletions(-) diff --git a/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java b/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java index c5c9a10dc5..3a9c2943c0 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java @@ -121,8 +121,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { private DeviceInfo deviceInfo; private int deviceVolume; private boolean isDeviceMuted; - private int audioSessionId; - private boolean skipSilenceEnabled; private Size surfaceSize; private boolean newlyRenderedFirstFrame; private Metadata timedMetadata; @@ -167,8 +165,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { deviceInfo = DeviceInfo.UNKNOWN; deviceVolume = 0; isDeviceMuted = false; - audioSessionId = C.AUDIO_SESSION_ID_UNSET; - skipSilenceEnabled = false; surfaceSize = Size.UNKNOWN; newlyRenderedFirstFrame = false; timedMetadata = new Metadata(/* presentationTimeUs= */ C.TIME_UNSET); @@ -213,8 +209,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { this.deviceInfo = state.deviceInfo; this.deviceVolume = state.deviceVolume; this.isDeviceMuted = state.isDeviceMuted; - this.audioSessionId = state.audioSessionId; - this.skipSilenceEnabled = state.skipSilenceEnabled; this.surfaceSize = state.surfaceSize; this.newlyRenderedFirstFrame = state.newlyRenderedFirstFrame; this.timedMetadata = state.timedMetadata; @@ -500,30 +494,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { return this; } - /** - * Sets the audio session id. - * - * @param audioSessionId The audio session id. - * @return This builder. - */ - @CanIgnoreReturnValue - public Builder setAudioSessionId(int audioSessionId) { - this.audioSessionId = audioSessionId; - return this; - } - - /** - * Sets whether skipping silences in the audio stream is enabled. - * - * @param skipSilenceEnabled Whether skipping silences in the audio stream is enabled. - * @return This builder. - */ - @CanIgnoreReturnValue - public Builder setSkipSilenceEnabled(boolean skipSilenceEnabled) { - this.skipSilenceEnabled = skipSilenceEnabled; - return this; - } - /** * Sets the size of the surface onto which the video is being rendered. * @@ -854,10 +824,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { public final int deviceVolume; /** Whether the device is muted. */ public final boolean isDeviceMuted; - /** The audio session id. */ - public final int audioSessionId; - /** Whether skipping silences in the audio stream is enabled. */ - public final boolean skipSilenceEnabled; /** The size of the surface onto which the video is being rendered. */ public final Size surfaceSize; /** @@ -998,8 +964,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { this.deviceInfo = builder.deviceInfo; this.deviceVolume = builder.deviceVolume; this.isDeviceMuted = builder.isDeviceMuted; - this.audioSessionId = builder.audioSessionId; - this.skipSilenceEnabled = builder.skipSilenceEnabled; this.surfaceSize = builder.surfaceSize; this.newlyRenderedFirstFrame = builder.newlyRenderedFirstFrame; this.timedMetadata = builder.timedMetadata; @@ -1055,8 +1019,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { && deviceInfo.equals(state.deviceInfo) && deviceVolume == state.deviceVolume && isDeviceMuted == state.isDeviceMuted - && audioSessionId == state.audioSessionId - && skipSilenceEnabled == state.skipSilenceEnabled && surfaceSize.equals(state.surfaceSize) && newlyRenderedFirstFrame == state.newlyRenderedFirstFrame && timedMetadata.equals(state.timedMetadata) @@ -1101,8 +1063,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { result = 31 * result + deviceInfo.hashCode(); result = 31 * result + deviceVolume; result = 31 * result + (isDeviceMuted ? 1 : 0); - result = 31 * result + audioSessionId; - result = 31 * result + (skipSilenceEnabled ? 1 : 0); result = 31 * result + surfaceSize.hashCode(); result = 31 * result + (newlyRenderedFirstFrame ? 1 : 0); result = 31 * result + timedMetadata.hashCode(); @@ -3009,11 +2969,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { Player.EVENT_PLAYBACK_PARAMETERS_CHANGED, listener -> listener.onPlaybackParametersChanged(newState.playbackParameters)); } - if (previousState.skipSilenceEnabled != newState.skipSilenceEnabled) { - listeners.queueEvent( - Player.EVENT_SKIP_SILENCE_ENABLED_CHANGED, - listener -> listener.onSkipSilenceEnabledChanged(newState.skipSilenceEnabled)); - } if (previousState.repeatMode != newState.repeatMode) { listeners.queueEvent( Player.EVENT_REPEAT_MODE_CHANGED, @@ -3060,11 +3015,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { Player.EVENT_PLAYLIST_METADATA_CHANGED, listener -> listener.onPlaylistMetadataChanged(newState.playlistMetadata)); } - if (previousState.audioSessionId != newState.audioSessionId) { - listeners.queueEvent( - Player.EVENT_AUDIO_SESSION_ID, - listener -> listener.onAudioSessionIdChanged(newState.audioSessionId)); - } if (newState.newlyRenderedFirstFrame) { listeners.queueEvent(Player.EVENT_RENDERED_FIRST_FRAME, Listener::onRenderedFirstFrame); } diff --git a/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java b/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java index ee56a1705b..ce94373e62 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/SimpleBasePlayerTest.java @@ -114,8 +114,6 @@ public class SimpleBasePlayerTest { new DeviceInfo( DeviceInfo.PLAYBACK_TYPE_LOCAL, /* minVolume= */ 3, /* maxVolume= */ 7)) .setIsDeviceMuted(true) - .setAudioSessionId(78) - .setSkipSilenceEnabled(true) .setSurfaceSize(new Size(480, 360)) .setNewlyRenderedFirstFrame(true) .setTimedMetadata(new Metadata()) @@ -276,8 +274,6 @@ public class SimpleBasePlayerTest { .setDeviceInfo(deviceInfo) .setDeviceVolume(5) .setIsDeviceMuted(true) - .setAudioSessionId(78) - .setSkipSilenceEnabled(true) .setSurfaceSize(surfaceSize) .setNewlyRenderedFirstFrame(true) .setTimedMetadata(timedMetadata) @@ -318,8 +314,6 @@ public class SimpleBasePlayerTest { assertThat(state.deviceInfo).isEqualTo(deviceInfo); assertThat(state.deviceVolume).isEqualTo(5); assertThat(state.isDeviceMuted).isTrue(); - assertThat(state.audioSessionId).isEqualTo(78); - assertThat(state.skipSilenceEnabled).isTrue(); assertThat(state.surfaceSize).isEqualTo(surfaceSize); assertThat(state.newlyRenderedFirstFrame).isTrue(); assertThat(state.timedMetadata).isEqualTo(timedMetadata); @@ -872,8 +866,6 @@ public class SimpleBasePlayerTest { .setDeviceInfo(deviceInfo) .setDeviceVolume(5) .setIsDeviceMuted(true) - .setAudioSessionId(78) - .setSkipSilenceEnabled(true) .setSurfaceSize(surfaceSize) .setPlaylist(playlist) .setPlaylistMetadata(playlistMetadata) @@ -1167,8 +1159,6 @@ public class SimpleBasePlayerTest { .setDeviceInfo(deviceInfo) .setDeviceVolume(5) .setIsDeviceMuted(true) - .setAudioSessionId(78) - .setSkipSilenceEnabled(true) .setSurfaceSize(surfaceSize) .setNewlyRenderedFirstFrame(true) .setTimedMetadata(timedMetadata) @@ -1234,11 +1224,9 @@ public class SimpleBasePlayerTest { verify(listener).onMediaMetadataChanged(mediaMetadata); verify(listener).onTracksChanged(tracks); verify(listener).onPlaylistMetadataChanged(playlistMetadata); - verify(listener).onAudioSessionIdChanged(78); verify(listener).onRenderedFirstFrame(); verify(listener).onMetadata(timedMetadata); verify(listener).onSurfaceSizeChanged(surfaceSize.getWidth(), surfaceSize.getHeight()); - verify(listener).onSkipSilenceEnabledChanged(true); verify(listener).onPositionDiscontinuity(Player.DISCONTINUITY_REASON_SEEK); verify(listener) .onPositionDiscontinuity( @@ -1291,9 +1279,7 @@ public class SimpleBasePlayerTest { Player.EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED, Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED, Player.EVENT_AUDIO_ATTRIBUTES_CHANGED, - Player.EVENT_AUDIO_SESSION_ID, Player.EVENT_VOLUME_CHANGED, - Player.EVENT_SKIP_SILENCE_ENABLED_CHANGED, Player.EVENT_SURFACE_SIZE_CHANGED, Player.EVENT_VIDEO_SIZE_CHANGED, Player.EVENT_RENDERED_FIRST_FRAME, @@ -1308,6 +1294,11 @@ public class SimpleBasePlayerTest { if (method.getName().equals("onSeekProcessed")) { continue; } + if (method.getName().equals("onAudioSessionIdChanged") + || method.getName().equals("onSkipSilenceEnabledChanged")) { + // Skip listeners for ExoPlayer-specific states + continue; + } method.invoke(verify(listener), getAnyArguments(method)); } } From 5f6fde4d2a90d78a8d58430c88d7dc12849fe163 Mon Sep 17 00:00:00 2001 From: ibaker Date: Fri, 2 Dec 2022 15:29:19 +0000 Subject: [PATCH 043/183] Fix `TextRenderer` exception when a subtitle file contains no cues Discovered while investigating Issue: google/ExoPlayer#10823 Example stack trace with the previous code (I added the index value for debugging): ``` playerFailed [eventTime=44.07, mediaPos=44.01, window=0, period=0, errorCode=ERROR_CODE_FAILED_RUNTIME_CHECK androidx.media3.exoplayer.ExoPlaybackException: Unexpected runtime error at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:635) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loopOnce(Looper.java:202) at android.os.Looper.loop(Looper.java:291) at android.os.HandlerThread.run(HandlerThread.java:67) Caused by: java.lang.IllegalArgumentException: index=-1 at androidx.media3.common.util.Assertions.checkArgument(Assertions.java:55) at androidx.media3.extractor.text.webvtt.WebvttSubtitle.getEventTime(WebvttSubtitle.java:62) at androidx.media3.extractor.text.SubtitleOutputBuffer.getEventTime(SubtitleOutputBuffer.java:56) at androidx.media3.exoplayer.text.TextRenderer.getCurrentEventTimeUs(TextRenderer.java:435) at androidx.media3.exoplayer.text.TextRenderer.render(TextRenderer.java:268) at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1008) at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:509) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loopOnce(Looper.java:202) at android.os.Looper.loop(Looper.java:291) at android.os.HandlerThread.run(HandlerThread.java:67) ] ``` #minor-release PiperOrigin-RevId: 492464180 --- .../java/com/google/android/exoplayer2/text/TextRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 58ead180c9..862463d33b 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 @@ -418,7 +418,7 @@ public final class TextRenderer extends BaseRenderer implements Callback { @SideEffectFree private long getCurrentEventTimeUs(long positionUs) { int nextEventTimeIndex = subtitle.getNextEventTimeIndex(positionUs); - if (nextEventTimeIndex == 0) { + if (nextEventTimeIndex == 0 || subtitle.getEventTimeCount() == 0) { return subtitle.timeUs; } From 2f8cf947c71db6be9459492117fe95b1a8bc7178 Mon Sep 17 00:00:00 2001 From: ibaker Date: Fri, 2 Dec 2022 16:05:02 +0000 Subject: [PATCH 044/183] Fix `ExoPlayerTest` to use `C.TIME_UNSET` instead of `C.POSITION_UNSET` This inconsistency was exposed by an upcoming change to deprecate `POSITION_UNSET` in favour of `INDEX_UNSET` because position is an ambiguous term between 'byte offset' and 'media position', as shown here. PiperOrigin-RevId: 492470241 --- .../java/com/google/android/exoplayer2/ExoPlayerTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 5b52e1f800..43c0480b57 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 @@ -2514,7 +2514,7 @@ public final class ExoPlayerTest { .build() .start() .blockUntilEnded(TIMEOUT_MS); - assertThat(target.positionMs).isEqualTo(C.POSITION_UNSET); + assertThat(target.positionMs).isEqualTo(C.TIME_UNSET); } @Test @@ -2536,7 +2536,7 @@ public final class ExoPlayerTest { .build() .start() .blockUntilEnded(TIMEOUT_MS); - assertThat(target.positionMs).isEqualTo(C.POSITION_UNSET); + assertThat(target.positionMs).isEqualTo(C.TIME_UNSET); } @Test @@ -12282,7 +12282,7 @@ public final class ExoPlayerTest { public PositionGrabbingMessageTarget() { mediaItemIndex = C.INDEX_UNSET; - positionMs = C.POSITION_UNSET; + positionMs = C.TIME_UNSET; } @Override From f3fc4fb9735a4b67a3740b3796495017eb5c978c Mon Sep 17 00:00:00 2001 From: tonihei Date: Fri, 2 Dec 2022 16:24:37 +0000 Subject: [PATCH 045/183] Fix threading of onFallbackApplied callback The callback is currently triggered on the ExoPlayer playback thread instead of the app thread that added the listener. PiperOrigin-RevId: 492474405 --- .../transformer/FallbackListener.java | 28 +++++++++++------ .../exoplayer2/transformer/Transformer.java | 6 +++- .../transformer/FallbackListenerTest.java | 31 ++++++++++++++++--- .../transformer/VideoEncoderWrapperTest.java | 1 + 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/FallbackListener.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/FallbackListener.java index 8f54f4cd8c..36ccf8c73d 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/FallbackListener.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/FallbackListener.java @@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkState; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.util.HandlerWrapper; import com.google.android.exoplayer2.util.ListenerSet; import com.google.android.exoplayer2.util.Util; @@ -32,6 +33,7 @@ import com.google.android.exoplayer2.util.Util; private final MediaItem mediaItem; private final TransformationRequest originalTransformationRequest; private final ListenerSet transformerListeners; + private final HandlerWrapper transformerListenerHandler; private TransformationRequest fallbackTransformationRequest; private int trackCount; @@ -40,16 +42,20 @@ import com.google.android.exoplayer2.util.Util; * Creates a new instance. * * @param mediaItem The {@link MediaItem} to transform. - * @param transformerListeners The {@linkplain Transformer.Listener listeners} to forward events - * to. + * @param transformerListeners The {@linkplain Transformer.Listener listeners} to call {@link + * Transformer.Listener#onFallbackApplied} on. + * @param transformerListenerHandler The {@link HandlerWrapper} to call {@link + * Transformer.Listener#onFallbackApplied} events on. * @param originalTransformationRequest The original {@link TransformationRequest}. */ public FallbackListener( MediaItem mediaItem, ListenerSet transformerListeners, + HandlerWrapper transformerListenerHandler, TransformationRequest originalTransformationRequest) { this.mediaItem = mediaItem; this.transformerListeners = transformerListeners; + this.transformerListenerHandler = transformerListenerHandler; this.originalTransformationRequest = originalTransformationRequest; this.fallbackTransformationRequest = originalTransformationRequest; } @@ -98,15 +104,19 @@ import com.google.android.exoplayer2.util.Util; if (transformationRequest.hdrMode != originalTransformationRequest.hdrMode) { fallbackRequestBuilder.setHdrMode(transformationRequest.hdrMode); } - fallbackTransformationRequest = fallbackRequestBuilder.build(); + TransformationRequest newFallbackTransformationRequest = fallbackRequestBuilder.build(); + fallbackTransformationRequest = newFallbackTransformationRequest; if (trackCount == 0 && !originalTransformationRequest.equals(fallbackTransformationRequest)) { - transformerListeners.queueEvent( - /* eventFlag= */ C.INDEX_UNSET, - listener -> - listener.onFallbackApplied( - mediaItem, originalTransformationRequest, fallbackTransformationRequest)); - transformerListeners.flushEvents(); + transformerListenerHandler.post( + () -> + transformerListeners.sendEvent( + /* eventFlag= */ C.INDEX_UNSET, + listener -> + listener.onFallbackApplied( + mediaItem, + originalTransformationRequest, + newFallbackTransformationRequest))); } } } 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 340d4b4254..6b21dc6707 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 @@ -752,7 +752,11 @@ public final class Transformer { TransformerInternalListener transformerInternalListener = new TransformerInternalListener(mediaItem); FallbackListener fallbackListener = - new FallbackListener(mediaItem, listeners, transformationRequest); + new FallbackListener( + mediaItem, + listeners, + clock.createHandler(looper, /* callback= */ null), + transformationRequest); transformerInternal = new TransformerInternal( context, diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/FallbackListenerTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/FallbackListenerTest.java index 60a26756b3..80aa79b069 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/FallbackListenerTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/FallbackListenerTest.java @@ -26,10 +26,12 @@ import android.os.Looper; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.MediaItem; 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.MimeTypes; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.shadows.ShadowLooper; /** Unit tests for {@link FallbackListener}. */ @RunWith(AndroidJUnit4.class) @@ -41,7 +43,8 @@ public class FallbackListenerTest { public void onTransformationRequestFinalized_withoutTrackRegistration_throwsException() { TransformationRequest transformationRequest = new TransformationRequest.Builder().build(); FallbackListener fallbackListener = - new FallbackListener(PLACEHOLDER_MEDIA_ITEM, createListenerSet(), transformationRequest); + new FallbackListener( + PLACEHOLDER_MEDIA_ITEM, createListenerSet(), createHandler(), transformationRequest); assertThrows( IllegalStateException.class, @@ -52,10 +55,12 @@ public class FallbackListenerTest { public void onTransformationRequestFinalized_afterTrackRegistration_completesSuccessfully() { TransformationRequest transformationRequest = new TransformationRequest.Builder().build(); FallbackListener fallbackListener = - new FallbackListener(PLACEHOLDER_MEDIA_ITEM, createListenerSet(), transformationRequest); + new FallbackListener( + PLACEHOLDER_MEDIA_ITEM, createListenerSet(), createHandler(), transformationRequest); fallbackListener.registerTrack(); fallbackListener.onTransformationRequestFinalized(transformationRequest); + ShadowLooper.idleMainLooper(); } @Test @@ -66,10 +71,14 @@ public class FallbackListenerTest { Transformer.Listener mockListener = mock(Transformer.Listener.class); FallbackListener fallbackListener = new FallbackListener( - PLACEHOLDER_MEDIA_ITEM, createListenerSet(mockListener), originalRequest); + PLACEHOLDER_MEDIA_ITEM, + createListenerSet(mockListener), + createHandler(), + originalRequest); fallbackListener.registerTrack(); fallbackListener.onTransformationRequestFinalized(unchangedRequest); + ShadowLooper.idleMainLooper(); verify(mockListener, never()).onFallbackApplied(any(), any(), any()); } @@ -83,10 +92,14 @@ public class FallbackListenerTest { Transformer.Listener mockListener = mock(Transformer.Listener.class); FallbackListener fallbackListener = new FallbackListener( - PLACEHOLDER_MEDIA_ITEM, createListenerSet(mockListener), originalRequest); + PLACEHOLDER_MEDIA_ITEM, + createListenerSet(mockListener), + createHandler(), + originalRequest); fallbackListener.registerTrack(); fallbackListener.onTransformationRequestFinalized(audioFallbackRequest); + ShadowLooper.idleMainLooper(); verify(mockListener) .onFallbackApplied(PLACEHOLDER_MEDIA_ITEM, originalRequest, audioFallbackRequest); @@ -109,12 +122,16 @@ public class FallbackListenerTest { Transformer.Listener mockListener = mock(Transformer.Listener.class); FallbackListener fallbackListener = new FallbackListener( - PLACEHOLDER_MEDIA_ITEM, createListenerSet(mockListener), originalRequest); + PLACEHOLDER_MEDIA_ITEM, + createListenerSet(mockListener), + createHandler(), + originalRequest); fallbackListener.registerTrack(); fallbackListener.registerTrack(); fallbackListener.onTransformationRequestFinalized(audioFallbackRequest); fallbackListener.onTransformationRequestFinalized(videoFallbackRequest); + ShadowLooper.idleMainLooper(); verify(mockListener) .onFallbackApplied(PLACEHOLDER_MEDIA_ITEM, originalRequest, mergedFallbackRequest); @@ -130,4 +147,8 @@ public class FallbackListenerTest { private static ListenerSet createListenerSet() { return new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, (listener, flags) -> {}); } + + private static HandlerWrapper createHandler() { + return Clock.DEFAULT.createHandler(Looper.myLooper(), /* callback= */ null); + } } diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java index 58a10c6380..0103f1e385 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/VideoEncoderWrapperTest.java @@ -50,6 +50,7 @@ public final class VideoEncoderWrapperTest { new FallbackListener( MediaItem.fromUri(Uri.EMPTY), new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, (listener, flags) -> {}), + Clock.DEFAULT.createHandler(Looper.myLooper(), /* callback= */ null), emptyTransformationRequest); private final VideoTranscodingSamplePipeline.EncoderWrapper encoderWrapper = new VideoTranscodingSamplePipeline.EncoderWrapper( From d6c872494be87058fc719af2bf3dbcf2879c7e9a Mon Sep 17 00:00:00 2001 From: ibaker Date: Fri, 2 Dec 2022 17:52:16 +0000 Subject: [PATCH 046/183] Deprecate `C.POSITION_UNSET` in favour of `C.INDEX_UNSET` These have the same value (`-1`), and basically the same meaning (offset in an array/list/file/byte stream/etc), but 'position' is an overloaded term in a media playback library, and there's a risk people assume that methods like `Player.getCurrentPosition()` may return `C.POSITION_UNSET`, when in fact unset media times (whether duration or position) are always represented by `C.TIME_UNSET` which is a) a `long` (not `int`) and b) a different underlying value. (aside: `getCurrentPosition()` never returns an unset value, but it's a good example of the ambiguity of the word 'position' between 'byte offset' and 'media timestamp'.) PiperOrigin-RevId: 492493102 --- .../java/com/google/android/exoplayer2/C.java | 8 +++-- .../audio/AudioTimestampPoller.java | 4 +-- .../source/BundledExtractorsAdapter.java | 2 +- .../source/MediaParserExtractorAdapter.java | 2 +- .../source/ProgressiveMediaExtractor.java | 4 +-- .../source/ProgressiveMediaPeriod.java | 2 +- .../exoplayer2/source/SampleDataQueue.java | 6 ++-- .../exoplayer2/source/SampleQueue.java | 8 ++--- .../mediaparser/InputReaderAdapterV30.java | 6 ++-- .../upstream/cache/CacheWriter.java | 8 ++--- .../extractor/BinarySearchSeeker.java | 2 +- .../extractor/avi/AviExtractor.java | 14 ++++---- .../extractor/jpeg/JpegExtractor.java | 4 +-- .../jpeg/MotionPhotoDescription.java | 8 ++--- .../extractor/mkv/MatroskaExtractor.java | 21 ++++++----- .../extractor/mp3/ConstantBitrateSeeker.java | 2 +- .../exoplayer2/extractor/mp3/MlltSeeker.java | 2 +- .../extractor/mp3/Mp3Extractor.java | 4 +-- .../exoplayer2/extractor/mp3/Seeker.java | 4 +-- .../exoplayer2/extractor/mp3/XingSeeker.java | 2 +- .../exoplayer2/extractor/mp4/AtomParsers.java | 12 +++---- .../extractor/mp4/Mp4Extractor.java | 2 +- .../extractor/ogg/DefaultOggSeeker.java | 12 +++---- .../extractor/ogg/OggPageHeader.java | 8 ++--- .../extractor/ts/AdtsExtractor.java | 4 +-- .../extractor/ts/PsBinarySearchSeeker.java | 4 +-- .../extractor/ts/SectionReader.java | 2 +- .../extractor/ts/TsBinarySearchSeeker.java | 4 +-- .../extractor/wav/WavExtractor.java | 8 ++--- .../exoplayer2/metadata/id3/ChapterFrame.java | 4 +-- .../exoplayer2/metadata/id3/Id3Decoder.java | 4 +-- .../exoplayer2/text/cea/Cea708Decoder.java | 36 +++++++++---------- .../extractor/ts/PsExtractorSeekTest.java | 2 +- .../android/exoplayer2/testutil/TestUtil.java | 2 +- 34 files changed, 109 insertions(+), 108 deletions(-) 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 ce6d067805..e4ad83bac7 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 @@ -60,11 +60,13 @@ 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 or byte position. */ public static final int INDEX_UNSET = -1; - /** Represents an unset or unknown position. */ - public static final int POSITION_UNSET = -1; + /** + * @deprecated Use {@link #INDEX_UNSET}. + */ + @Deprecated public static final int POSITION_UNSET = INDEX_UNSET; /** Represents an unset or unknown rate. */ public static final float RATE_UNSET = -Float.MAX_VALUE; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTimestampPoller.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTimestampPoller.java index 537cd0791c..380c2fc1f3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTimestampPoller.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTimestampPoller.java @@ -237,7 +237,7 @@ import java.lang.annotation.Target; */ @TargetApi(19) // audioTimestamp will be null if Util.SDK_INT < 19. public long getTimestampPositionFrames() { - return audioTimestamp != null ? audioTimestamp.getTimestampPositionFrames() : C.POSITION_UNSET; + return audioTimestamp != null ? audioTimestamp.getTimestampPositionFrames() : C.INDEX_UNSET; } private void updateState(@State int state) { @@ -246,7 +246,7 @@ import java.lang.annotation.Target; case STATE_INITIALIZING: // Force polling a timestamp immediately, and poll quickly. lastTimestampSampleTimeUs = 0; - initialTimestampPositionFrames = C.POSITION_UNSET; + initialTimestampPositionFrames = C.INDEX_UNSET; initializeSystemTimeUs = System.nanoTime() / 1000; sampleIntervalUs = FAST_POLL_INTERVAL_US; break; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/BundledExtractorsAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/source/BundledExtractorsAdapter.java index edb16e53d6..7c9a579adc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/BundledExtractorsAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/BundledExtractorsAdapter.java @@ -113,7 +113,7 @@ public final class BundledExtractorsAdapter implements ProgressiveMediaExtractor @Override public long getCurrentInputPosition() { - return extractorInput != null ? extractorInput.getPosition() : C.POSITION_UNSET; + return extractorInput != null ? extractorInput.getPosition() : C.INDEX_UNSET; } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaParserExtractorAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaParserExtractorAdapter.java index 51926cdf43..944eaa8c87 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaParserExtractorAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaParserExtractorAdapter.java @@ -126,7 +126,7 @@ public final class MediaParserExtractorAdapter implements ProgressiveMediaExtrac positionHolder.position = inputReaderAdapter.getAndResetSeekPosition(); return !shouldContinue ? Extractor.RESULT_END_OF_INPUT - : positionHolder.position != C.POSITION_UNSET + : positionHolder.position != C.INDEX_UNSET ? Extractor.RESULT_SEEK : Extractor.RESULT_CONTINUE; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaExtractor.java index 7de4d5d291..69729b954c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaExtractor.java @@ -73,8 +73,8 @@ public interface ProgressiveMediaExtractor { void disableSeekingOnMp3Streams(); /** - * Returns the current read position in the input stream, or {@link C#POSITION_UNSET} if no input - * is available. + * Returns the current read position in the input stream, or {@link C#INDEX_UNSET} if no input is + * available. */ long getCurrentInputPosition(); 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 b29338f86e..c3ccc069bb 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 @@ -1047,7 +1047,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } finally { if (result == Extractor.RESULT_SEEK) { result = Extractor.RESULT_CONTINUE; - } else if (progressiveMediaExtractor.getCurrentInputPosition() != C.POSITION_UNSET) { + } else if (progressiveMediaExtractor.getCurrentInputPosition() != C.INDEX_UNSET) { positionHolder.position = progressiveMediaExtractor.getCurrentInputPosition(); } DataSourceUtil.closeQuietly(dataSource); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleDataQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleDataQueue.java index 00b1943533..ef28bff90e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleDataQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleDataQueue.java @@ -146,11 +146,11 @@ import java.util.Arrays; /** * Advances the read position to the specified absolute position. * - * @param absolutePosition The new absolute read position. May be {@link C#POSITION_UNSET}, in - * which case calling this method is a no-op. + * @param absolutePosition The new absolute read position. May be {@link C#INDEX_UNSET}, in which + * case calling this method is a no-op. */ public void discardDownstreamTo(long absolutePosition) { - if (absolutePosition == C.POSITION_UNSET) { + if (absolutePosition == C.INDEX_UNSET) { return; } while (absolutePosition >= firstAllocationNode.endPosition) { 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 c6112c67f8..0b90c3965c 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 @@ -752,26 +752,26 @@ public class SampleQueue implements TrackOutput { private synchronized long discardSampleMetadataTo( long timeUs, boolean toKeyframe, boolean stopAtReadPosition) { if (length == 0 || timeUs < timesUs[relativeFirstIndex]) { - return C.POSITION_UNSET; + return C.INDEX_UNSET; } int searchLength = stopAtReadPosition && readPosition != length ? readPosition + 1 : length; int discardCount = findSampleBefore(relativeFirstIndex, searchLength, timeUs, toKeyframe); if (discardCount == -1) { - return C.POSITION_UNSET; + return C.INDEX_UNSET; } return discardSamples(discardCount); } public synchronized long discardSampleMetadataToRead() { if (readPosition == 0) { - return C.POSITION_UNSET; + return C.INDEX_UNSET; } return discardSamples(readPosition); } private synchronized long discardSampleMetadataToEnd() { if (length == 0) { - return C.POSITION_UNSET; + return C.INDEX_UNSET; } return discardSamples(length); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/mediaparser/InputReaderAdapterV30.java b/library/core/src/main/java/com/google/android/exoplayer2/source/mediaparser/InputReaderAdapterV30.java index 3a55645e96..aec49478fb 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/mediaparser/InputReaderAdapterV30.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/mediaparser/InputReaderAdapterV30.java @@ -43,7 +43,7 @@ public final class InputReaderAdapterV30 implements MediaParser.SeekableInputRea public void setDataReader(DataReader dataReader, long length) { this.dataReader = dataReader; resourceLength = length; - lastSeekPosition = C.POSITION_UNSET; + lastSeekPosition = C.INDEX_UNSET; } /** Sets the absolute position in the resource from which the wrapped {@link DataReader} reads. */ @@ -53,11 +53,11 @@ public final class InputReaderAdapterV30 implements MediaParser.SeekableInputRea /** * Returns the last value passed to {@link #seekToPosition(long)} and sets the stored value to - * {@link C#POSITION_UNSET}. + * {@link C#INDEX_UNSET}. */ public long getAndResetSeekPosition() { long lastSeekPosition = this.lastSeekPosition; - this.lastSeekPosition = C.POSITION_UNSET; + this.lastSeekPosition = C.INDEX_UNSET; return lastSeekPosition; } diff --git a/library/datasource/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheWriter.java b/library/datasource/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheWriter.java index 5fa6638981..a0f898bf6b 100644 --- a/library/datasource/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheWriter.java +++ b/library/datasource/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheWriter.java @@ -114,16 +114,16 @@ public final class CacheWriter { endPosition = dataSpec.position + dataSpec.length; } else { long contentLength = ContentMetadata.getContentLength(cache.getContentMetadata(cacheKey)); - endPosition = contentLength == C.LENGTH_UNSET ? C.POSITION_UNSET : contentLength; + endPosition = contentLength == C.LENGTH_UNSET ? C.INDEX_UNSET : contentLength; } if (progressListener != null) { progressListener.onProgress(getLength(), bytesCached, /* newBytesCached= */ 0); } - while (endPosition == C.POSITION_UNSET || nextPosition < endPosition) { + while (endPosition == C.INDEX_UNSET || nextPosition < endPosition) { throwIfCanceled(); long maxRemainingLength = - endPosition == C.POSITION_UNSET ? Long.MAX_VALUE : endPosition - nextPosition; + endPosition == C.INDEX_UNSET ? Long.MAX_VALUE : endPosition - nextPosition; long blockLength = cache.getCachedLength(cacheKey, nextPosition, maxRemainingLength); if (blockLength > 0) { nextPosition += blockLength; @@ -223,7 +223,7 @@ public final class CacheWriter { } private long getLength() { - return endPosition == C.POSITION_UNSET ? C.LENGTH_UNSET : endPosition - dataSpec.position; + return endPosition == C.INDEX_UNSET ? C.LENGTH_UNSET : endPosition - dataSpec.position; } private void throwIfCanceled() throws InterruptedIOException { diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java index 80ab98a6d1..2e578b2538 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java @@ -418,7 +418,7 @@ public abstract class BinarySearchSeeker { @interface Type {} public static final TimestampSearchResult NO_TIMESTAMP_IN_RANGE_RESULT = - new TimestampSearchResult(TYPE_NO_TIMESTAMP, C.TIME_UNSET, C.POSITION_UNSET); + new TimestampSearchResult(TYPE_NO_TIMESTAMP, C.TIME_UNSET, C.INDEX_UNSET); /** The type of the result. */ private final @Type int type; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java index e59ba61f7e..c482ffce62 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java @@ -142,8 +142,8 @@ public final class AviExtractor implements Extractor { chunkHeaderHolder = new ChunkHeaderHolder(); extractorOutput = new DummyExtractorOutput(); chunkReaders = new ChunkReader[0]; - moviStart = C.POSITION_UNSET; - moviEnd = C.POSITION_UNSET; + moviStart = C.INDEX_UNSET; + moviEnd = C.INDEX_UNSET; hdrlSize = C.LENGTH_UNSET; durationUs = C.TIME_UNSET; } @@ -154,7 +154,7 @@ public final class AviExtractor implements Extractor { public void init(ExtractorOutput output) { this.state = STATE_SKIPPING_TO_HDRL; this.extractorOutput = output; - pendingReposition = C.POSITION_UNSET; + pendingReposition = C.INDEX_UNSET; } @Override @@ -206,7 +206,7 @@ public final class AviExtractor implements Extractor { state = STATE_FINDING_MOVI_HEADER; return RESULT_CONTINUE; case STATE_FINDING_MOVI_HEADER: - if (moviStart != C.POSITION_UNSET && input.getPosition() != moviStart) { + if (moviStart != C.INDEX_UNSET && input.getPosition() != moviStart) { pendingReposition = moviStart; return RESULT_CONTINUE; } @@ -273,7 +273,7 @@ public final class AviExtractor implements Extractor { @Override public void seek(long position, long timeUs) { - pendingReposition = C.POSITION_UNSET; + pendingReposition = C.INDEX_UNSET; currentChunkReader = null; for (ChunkReader chunkReader : chunkReaders) { chunkReader.seekToPosition(position); @@ -306,7 +306,7 @@ public final class AviExtractor implements Extractor { private boolean resolvePendingReposition(ExtractorInput input, PositionHolder seekPosition) throws IOException { boolean needSeek = false; - if (pendingReposition != C.POSITION_UNSET) { + if (pendingReposition != C.INDEX_UNSET) { long currentPosition = input.getPosition(); if (pendingReposition < currentPosition || pendingReposition > currentPosition + RELOAD_MINIMUM_SEEK_DISTANCE) { @@ -318,7 +318,7 @@ public final class AviExtractor implements Extractor { input.skipFully((int) (pendingReposition - currentPosition)); } } - pendingReposition = C.POSITION_UNSET; + pendingReposition = C.INDEX_UNSET; return needSeek; } 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 e4a5e8a863..b3de2d2975 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 @@ -94,7 +94,7 @@ public final class JpegExtractor implements Extractor { public JpegExtractor() { scratch = new ParsableByteArray(EXIF_ID_CODE_LENGTH); - mp4StartPosition = C.POSITION_UNSET; + mp4StartPosition = C.INDEX_UNSET; } @Override @@ -200,7 +200,7 @@ public final class JpegExtractor implements Extractor { input.readFully(scratch.getData(), /* offset= */ 0, /* length= */ 2); marker = scratch.readUnsignedShort(); if (marker == MARKER_SOS) { // Start of scan. - if (mp4StartPosition != C.POSITION_UNSET) { + if (mp4StartPosition != C.INDEX_UNSET) { state = STATE_SNIFFING_MOTION_PHOTO_VIDEO; } else { endReadingWithImageTrack(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/MotionPhotoDescription.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/MotionPhotoDescription.java index 3117dfa5f4..395e632302 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/MotionPhotoDescription.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/jpeg/MotionPhotoDescription.java @@ -81,9 +81,9 @@ import java.util.List; // Iterate backwards through the items to find the earlier video in the list. If we find a video // item with length zero, we need to keep scanning backwards to find the preceding item with // non-zero length, which is the item that contains the video data. - long photoStartPosition = C.POSITION_UNSET; + long photoStartPosition = C.INDEX_UNSET; long photoLength = C.LENGTH_UNSET; - long mp4StartPosition = C.POSITION_UNSET; + long mp4StartPosition = C.INDEX_UNSET; long mp4Length = C.LENGTH_UNSET; boolean itemContainsMp4 = false; long itemStartPosition = motionPhotoLength; @@ -110,9 +110,9 @@ import java.util.List; photoLength = itemEndPosition; } } - if (mp4StartPosition == C.POSITION_UNSET + if (mp4StartPosition == C.INDEX_UNSET || mp4Length == C.LENGTH_UNSET - || photoStartPosition == C.POSITION_UNSET + || photoStartPosition == C.INDEX_UNSET || photoLength == C.LENGTH_UNSET) { return null; } 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 eb60880cda..c62e70815c 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 @@ -394,7 +394,7 @@ public class MatroskaExtractor implements Extractor { private @MonotonicNonNull ByteBuffer encryptionSubsampleDataBuffer; private long segmentContentSize; - private long segmentContentPosition = C.POSITION_UNSET; + private long segmentContentPosition = C.INDEX_UNSET; private long timecodeScale = C.TIME_UNSET; private long durationTimecode = C.TIME_UNSET; private long durationUs = C.TIME_UNSET; @@ -411,8 +411,8 @@ public class MatroskaExtractor implements Extractor { // Cue related elements. private boolean seekForCues; - private long cuesContentPosition = C.POSITION_UNSET; - private long seekPositionAfterBuildingCues = C.POSITION_UNSET; + private long cuesContentPosition = C.INDEX_UNSET; + private long seekPositionAfterBuildingCues = C.INDEX_UNSET; private long clusterTimecodeUs = C.TIME_UNSET; @Nullable private LongArray cueTimesUs; @Nullable private LongArray cueClusterPositions; @@ -656,8 +656,7 @@ public class MatroskaExtractor implements Extractor { assertInitialized(); switch (id) { case ID_SEGMENT: - if (segmentContentPosition != C.POSITION_UNSET - && segmentContentPosition != contentPosition) { + if (segmentContentPosition != C.INDEX_UNSET && segmentContentPosition != contentPosition) { throw ParserException.createForMalformedContainer( "Multiple Segment elements not supported", /* cause= */ null); } @@ -666,7 +665,7 @@ public class MatroskaExtractor implements Extractor { break; case ID_SEEK: seekEntryId = UNSET_ENTRY_ID; - seekEntryPosition = C.POSITION_UNSET; + seekEntryPosition = C.INDEX_UNSET; break; case ID_CUES: cueTimesUs = new LongArray(); @@ -678,7 +677,7 @@ public class MatroskaExtractor implements Extractor { case ID_CLUSTER: if (!sentSeekMap) { // We need to build cues before parsing the cluster. - if (seekForCuesEnabled && cuesContentPosition != C.POSITION_UNSET) { + if (seekForCuesEnabled && cuesContentPosition != C.INDEX_UNSET) { // We know where the Cues element is located. Seek to request it. seekForCues = true; } else { @@ -729,7 +728,7 @@ public class MatroskaExtractor implements Extractor { } break; case ID_SEEK: - if (seekEntryId == UNSET_ENTRY_ID || seekEntryPosition == C.POSITION_UNSET) { + if (seekEntryId == UNSET_ENTRY_ID || seekEntryPosition == C.INDEX_UNSET) { throw ParserException.createForMalformedContainer( "Mandatory element SeekID or SeekPosition not found", /* cause= */ null); } @@ -1790,7 +1789,7 @@ public class MatroskaExtractor implements Extractor { */ private SeekMap buildSeekMap( @Nullable LongArray cueTimesUs, @Nullable LongArray cueClusterPositions) { - if (segmentContentPosition == C.POSITION_UNSET + if (segmentContentPosition == C.INDEX_UNSET || durationUs == C.TIME_UNSET || cueTimesUs == null || cueTimesUs.size() == 0 @@ -1846,9 +1845,9 @@ public class MatroskaExtractor implements Extractor { } // After parsing Cues, seek back to original position if available. We will not do this unless // we seeked to get to the Cues in the first place. - if (sentSeekMap && seekPositionAfterBuildingCues != C.POSITION_UNSET) { + if (sentSeekMap && seekPositionAfterBuildingCues != C.INDEX_UNSET) { seekPosition.position = seekPositionAfterBuildingCues; - seekPositionAfterBuildingCues = C.POSITION_UNSET; + seekPositionAfterBuildingCues = C.INDEX_UNSET; return true; } return false; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/ConstantBitrateSeeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/ConstantBitrateSeeker.java index 9762f2d0e5..f40a0fec64 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/ConstantBitrateSeeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/ConstantBitrateSeeker.java @@ -54,6 +54,6 @@ import com.google.android.exoplayer2.extractor.ConstantBitrateSeekMap; @Override public long getDataEndPosition() { - return C.POSITION_UNSET; + return C.INDEX_UNSET; } } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/MlltSeeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/MlltSeeker.java index 2204cfccd7..da4a413790 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/MlltSeeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/MlltSeeker.java @@ -125,6 +125,6 @@ import com.google.android.exoplayer2.util.Util; @Override public long getDataEndPosition() { - return C.POSITION_UNSET; + return C.INDEX_UNSET; } } 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 40bf68e152..d80427256f 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 @@ -426,7 +426,7 @@ public final class Mp3Extractor implements Extractor { private boolean peekEndOfStreamOrHeader(ExtractorInput extractorInput) throws IOException { if (seeker != null) { long dataEndPosition = seeker.getDataEndPosition(); - if (dataEndPosition != C.POSITION_UNSET + if (dataEndPosition != C.INDEX_UNSET && extractorInput.getPeekPosition() > dataEndPosition - 4) { return true; } @@ -452,7 +452,7 @@ public final class Mp3Extractor implements Extractor { @Nullable Seeker resultSeeker = null; if ((flags & FLAG_ENABLE_INDEX_SEEKING) != 0) { long durationUs; - long dataEndPosition = C.POSITION_UNSET; + long dataEndPosition = C.INDEX_UNSET; if (metadataSeeker != null) { durationUs = metadataSeeker.getDurationUs(); dataEndPosition = metadataSeeker.getDataEndPosition(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/Seeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/Seeker.java index c5b7550f2d..c959109a3d 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/Seeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp3/Seeker.java @@ -35,7 +35,7 @@ import com.google.android.exoplayer2.extractor.SeekMap; /** * Returns the position (byte offset) in the stream that is immediately after audio data, or - * {@link C#POSITION_UNSET} if not known. + * {@link C#INDEX_UNSET} if not known. */ long getDataEndPosition(); @@ -54,7 +54,7 @@ import com.google.android.exoplayer2.extractor.SeekMap; @Override public long getDataEndPosition() { // Position unset as we do not know the data end position. Note that returning 0 doesn't work. - return C.POSITION_UNSET; + return C.INDEX_UNSET; } } } 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 51950e6282..94b5dc4233 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 @@ -114,7 +114,7 @@ import com.google.android.exoplayer2.util.Util; this.durationUs = durationUs; this.tableOfContents = tableOfContents; this.dataSize = dataSize; - dataEndPosition = dataSize == C.LENGTH_UNSET ? C.POSITION_UNSET : dataStartPosition + dataSize; + dataEndPosition = dataSize == C.LENGTH_UNSET ? C.INDEX_UNSET : dataStartPosition + dataSize; } @Override 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 ec5c6fdd92..c5a128ea4b 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 @@ -1515,7 +1515,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; childAtomType == Atom.TYPE_esds ? childPosition : findBoxPosition(parent, Atom.TYPE_esds, childPosition, childAtomSize); - if (esdsAtomPosition != C.POSITION_UNSET) { + if (esdsAtomPosition != C.INDEX_UNSET) { esdsData = parseEsdsFromParent(parent, esdsAtomPosition); mimeType = esdsData.mimeType; @Nullable byte[] initializationDataBytes = esdsData.initializationData; @@ -1623,7 +1623,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; /** * Returns the position of the first box with the given {@code boxType} within {@code parent}, or - * {@link C#POSITION_UNSET} if no such box is found. + * {@link C#INDEX_UNSET} if no such box is found. * * @param parent The {@link ParsableByteArray} to search. The search will start from the {@link * ParsableByteArray#getPosition() current position}. @@ -1631,7 +1631,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; * @param parentBoxPosition The position in {@code parent} of the box we are searching. * @param parentBoxSize The size of the parent box we are searching in bytes. * @return The position of the first box with the given {@code boxType} within {@code parent}, or - * {@link C#POSITION_UNSET} if no such box is found. + * {@link C#INDEX_UNSET} if no such box is found. */ private static int findBoxPosition( ParsableByteArray parent, int boxType, int parentBoxPosition, int parentBoxSize) @@ -1648,7 +1648,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } childAtomPosition += childAtomSize; } - return C.POSITION_UNSET; + return C.INDEX_UNSET; } /** Returns codec-specific initialization data contained in an esds box. */ @@ -1736,7 +1736,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; /* package */ static Pair parseCommonEncryptionSinfFromParent( ParsableByteArray parent, int position, int size) throws ParserException { int childPosition = position + Atom.HEADER_SIZE; - int schemeInformationBoxPosition = C.POSITION_UNSET; + int schemeInformationBoxPosition = C.INDEX_UNSET; int schemeInformationBoxSize = 0; @Nullable String schemeType = null; @Nullable Integer dataFormat = null; @@ -1763,7 +1763,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; || C.CENC_TYPE_cbcs.equals(schemeType)) { ExtractorUtil.checkContainerInput(dataFormat != null, "frma atom is mandatory"); ExtractorUtil.checkContainerInput( - schemeInformationBoxPosition != C.POSITION_UNSET, "schi atom is mandatory"); + schemeInformationBoxPosition != C.INDEX_UNSET, "schi atom is mandatory"); @Nullable TrackEncryptionBox encryptionBox = parseSchiFromParent( 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 5197f2da08..7816d06640 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 @@ -302,7 +302,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { long firstTimeUs; long firstOffset; long secondTimeUs = C.TIME_UNSET; - long secondOffset = C.POSITION_UNSET; + long secondOffset = C.INDEX_UNSET; // Note that the id matches the index in tracks. int mainTrackIndex = trackId != C.INDEX_UNSET ? trackId : firstVideoTrackIndex; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java index 29a0f5932a..db11708ff5 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java @@ -109,7 +109,7 @@ import java.io.IOException; return positionBeforeSeekToEnd; case STATE_SEEK: long position = getNextSeekPosition(input); - if (position != C.POSITION_UNSET) { + if (position != C.INDEX_UNSET) { return position; } state = STATE_SKIP; @@ -142,18 +142,18 @@ import java.io.IOException; /** * Performs a single step of a seeking binary search, returning the byte position from which data - * should be provided for the next step, or {@link C#POSITION_UNSET} if the search has converged. - * If the search has converged then {@link #skipToPageOfTargetGranule(ExtractorInput)} should be + * should be provided for the next step, or {@link C#INDEX_UNSET} if the search has converged. If + * the search has converged then {@link #skipToPageOfTargetGranule(ExtractorInput)} should be * called to skip to the target page. * * @param input The {@link ExtractorInput} to read from. * @return The byte position from which data should be provided for the next step, or {@link - * C#POSITION_UNSET} if the search has converged. + * C#INDEX_UNSET} if the search has converged. * @throws IOException If reading from the input fails. */ private long getNextSeekPosition(ExtractorInput input) throws IOException { if (start == end) { - return C.POSITION_UNSET; + return C.INDEX_UNSET; } long currentPosition = input.getPosition(); @@ -170,7 +170,7 @@ import java.io.IOException; long granuleDistance = targetGranule - pageHeader.granulePosition; int pageSize = pageHeader.headerSize + pageHeader.bodySize; if (0 <= granuleDistance && granuleDistance < MATCH_RANGE) { - return C.POSITION_UNSET; + return C.INDEX_UNSET; } if (granuleDistance < 0) { 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 306e64f559..a0ed53ebae 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 @@ -79,7 +79,7 @@ import java.io.IOException; * *\/ C.POSITION_UNSET)}. */ public boolean skipToNextPage(ExtractorInput input) throws IOException { - return skipToNextPage(input, /* limit= */ C.POSITION_UNSET); + return skipToNextPage(input, /* limit= */ C.INDEX_UNSET); } /** @@ -94,7 +94,7 @@ import java.io.IOException; * * @param input The {@link ExtractorInput} to read from (must have {@code readPosition == * peekPosition}). - * @param limit The max position in {@code input} to peek to, or {@link C#POSITION_UNSET} to allow + * @param limit The max position in {@code input} to peek to, or {@link C#INDEX_UNSET} to allow * peeking to the end. * @return True if a capture_pattern was found. * @throws IOException If reading data fails. @@ -102,7 +102,7 @@ import java.io.IOException; public boolean skipToNextPage(ExtractorInput input, long limit) throws IOException { Assertions.checkArgument(input.getPosition() == input.getPeekPosition()); scratch.reset(/* limit= */ CAPTURE_PATTERN_SIZE); - while ((limit == C.POSITION_UNSET || input.getPosition() + CAPTURE_PATTERN_SIZE < limit) + while ((limit == C.INDEX_UNSET || input.getPosition() + CAPTURE_PATTERN_SIZE < limit) && peekFullyQuietly( input, scratch.getData(), 0, CAPTURE_PATTERN_SIZE, /* allowEndOfInput= */ true)) { scratch.setPosition(0); @@ -114,7 +114,7 @@ import java.io.IOException; input.skipFully(1); } // Move the read & peek positions to limit or end-of-input, whichever is closer. - while ((limit == C.POSITION_UNSET || input.getPosition() < limit) + while ((limit == C.INDEX_UNSET || input.getPosition() < limit) && input.skip(1) != C.RESULT_END_OF_INPUT) {} return false; } 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 e704f2ff89..0dbf52d236 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 @@ -130,7 +130,7 @@ public final class AdtsExtractor implements Extractor { reader = new AdtsReader(true); packetBuffer = new ParsableByteArray(MAX_PACKET_SIZE); averageFrameSize = C.LENGTH_UNSET; - firstFramePosition = C.POSITION_UNSET; + firstFramePosition = C.INDEX_UNSET; // Allocate scratch space for an ID3 header. The same buffer is also used to read 4 byte values. scratch = new ParsableByteArray(ID3_HEADER_LENGTH); scratchBits = new ParsableBitArray(scratch.getData()); @@ -256,7 +256,7 @@ public final class AdtsExtractor implements Extractor { } input.resetPeekPosition(); input.advancePeekPosition(firstFramePosition); - if (this.firstFramePosition == C.POSITION_UNSET) { + if (this.firstFramePosition == C.INDEX_UNSET) { this.firstFramePosition = firstFramePosition; } return firstFramePosition; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PsBinarySearchSeeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PsBinarySearchSeeker.java index 3616a0c354..16f5223dc4 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PsBinarySearchSeeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PsBinarySearchSeeker.java @@ -89,8 +89,8 @@ import java.io.IOException; private TimestampSearchResult searchForScrValueInBuffer( ParsableByteArray packetBuffer, long targetScrTimeUs, long bufferStartOffset) { - int startOfLastPacketPosition = C.POSITION_UNSET; - int endOfLastPacketPosition = C.POSITION_UNSET; + int startOfLastPacketPosition = C.INDEX_UNSET; + int endOfLastPacketPosition = C.INDEX_UNSET; long lastScrTimeUsInRange = C.TIME_UNSET; while (packetBuffer.bytesLeft() >= 4) { 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 4a73799c07..d39296836c 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 @@ -64,7 +64,7 @@ public final class SectionReader implements TsPayloadReader { @Override public void consume(ParsableByteArray data, @Flags int flags) { boolean payloadUnitStartIndicator = (flags & FLAG_PAYLOAD_UNIT_START_INDICATOR) != 0; - int payloadStartPosition = C.POSITION_UNSET; + int payloadStartPosition = C.INDEX_UNSET; if (payloadUnitStartIndicator) { int payloadStartOffset = data.readUnsignedByte(); payloadStartPosition = data.getPosition() + payloadStartOffset; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsBinarySearchSeeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsBinarySearchSeeker.java index fa9792079c..ec633efa9c 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsBinarySearchSeeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/TsBinarySearchSeeker.java @@ -96,8 +96,8 @@ import java.io.IOException; ParsableByteArray packetBuffer, long targetPcrTimeUs, long bufferStartOffset) { int limit = packetBuffer.limit(); - long startOfLastPacketPosition = C.POSITION_UNSET; - long endOfLastPacketPosition = C.POSITION_UNSET; + long startOfLastPacketPosition = C.INDEX_UNSET; + long endOfLastPacketPosition = C.INDEX_UNSET; long lastPcrTimeUsInRange = C.TIME_UNSET; while (packetBuffer.bytesLeft() >= TsExtractor.TS_PACKET_SIZE) { 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 8d64cb0255..a5ca847087 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 @@ -90,8 +90,8 @@ public final class WavExtractor implements Extractor { public WavExtractor() { state = STATE_READING_FILE_TYPE; rf64SampleDataSize = C.LENGTH_UNSET; - dataStartPosition = C.POSITION_UNSET; - dataEndPosition = C.POSITION_UNSET; + dataStartPosition = C.INDEX_UNSET; + dataEndPosition = C.INDEX_UNSET; } @Override @@ -151,7 +151,7 @@ public final class WavExtractor implements Extractor { private void readFileType(ExtractorInput input) throws IOException { Assertions.checkState(input.getPosition() == 0); - if (dataStartPosition != C.POSITION_UNSET) { + if (dataStartPosition != C.INDEX_UNSET) { input.skipFully(dataStartPosition); state = STATE_READING_SAMPLE_DATA; return; @@ -226,7 +226,7 @@ public final class WavExtractor implements Extractor { } private @ReadResult int readSampleData(ExtractorInput input) throws IOException { - Assertions.checkState(dataEndPosition != C.POSITION_UNSET); + Assertions.checkState(dataEndPosition != C.INDEX_UNSET); long bytesLeft = dataEndPosition - input.getPosition(); return Assertions.checkNotNull(outputWriter).sampleData(input, bytesLeft) ? RESULT_END_OF_INPUT diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java b/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java index e759a73aac..a9b4d5ebfd 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java @@ -31,9 +31,9 @@ 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#INDEX_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#INDEX_UNSET} if not set. */ public final long endOffset; private final Id3Frame[] subFrames; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java b/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java index 0ee41664e4..505aa64bd8 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java @@ -657,11 +657,11 @@ public final class Id3Decoder extends SimpleMetadataDecoder { int endTime = id3Data.readInt(); long startOffset = id3Data.readUnsignedInt(); if (startOffset == 0xFFFFFFFFL) { - startOffset = C.POSITION_UNSET; + startOffset = C.INDEX_UNSET; } long endOffset = id3Data.readUnsignedInt(); if (endOffset == 0xFFFFFFFFL) { - endOffset = C.POSITION_UNSET; + endOffset = C.INDEX_UNSET; } ArrayList subFrames = new ArrayList<>(); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java b/library/extractor/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java index e9a7be7015..a8f2b2dd0a 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java @@ -1005,10 +1005,10 @@ public final class Cea708Decoder extends CeaDecoder { public void clear() { rolledUpCaptions.clear(); captionStringBuilder.clear(); - italicsStartPosition = C.POSITION_UNSET; - underlineStartPosition = C.POSITION_UNSET; - foregroundColorStartPosition = C.POSITION_UNSET; - backgroundColorStartPosition = C.POSITION_UNSET; + italicsStartPosition = C.INDEX_UNSET; + underlineStartPosition = C.INDEX_UNSET; + foregroundColorStartPosition = C.INDEX_UNSET; + backgroundColorStartPosition = C.INDEX_UNSET; row = 0; } @@ -1120,27 +1120,27 @@ public final class Cea708Decoder extends CeaDecoder { // TODO: Add support for other offsets. // TODO: Add support for other pen sizes. - if (italicsStartPosition != C.POSITION_UNSET) { + if (italicsStartPosition != C.INDEX_UNSET) { if (!italicsToggle) { captionStringBuilder.setSpan( new StyleSpan(Typeface.ITALIC), italicsStartPosition, captionStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - italicsStartPosition = C.POSITION_UNSET; + italicsStartPosition = C.INDEX_UNSET; } } else if (italicsToggle) { italicsStartPosition = captionStringBuilder.length(); } - if (underlineStartPosition != C.POSITION_UNSET) { + if (underlineStartPosition != C.INDEX_UNSET) { if (!underlineToggle) { captionStringBuilder.setSpan( new UnderlineSpan(), underlineStartPosition, captionStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - underlineStartPosition = C.POSITION_UNSET; + underlineStartPosition = C.INDEX_UNSET; } } else if (underlineToggle) { underlineStartPosition = captionStringBuilder.length(); @@ -1151,7 +1151,7 @@ public final class Cea708Decoder extends CeaDecoder { } public void setPenColor(int foregroundColor, int backgroundColor, int edgeColor) { - if (foregroundColorStartPosition != C.POSITION_UNSET) { + if (foregroundColorStartPosition != C.INDEX_UNSET) { if (this.foregroundColor != foregroundColor) { captionStringBuilder.setSpan( new ForegroundColorSpan(this.foregroundColor), @@ -1165,7 +1165,7 @@ public final class Cea708Decoder extends CeaDecoder { this.foregroundColor = foregroundColor; } - if (backgroundColorStartPosition != C.POSITION_UNSET) { + if (backgroundColorStartPosition != C.INDEX_UNSET) { if (this.backgroundColor != backgroundColor) { captionStringBuilder.setSpan( new BackgroundColorSpan(this.backgroundColor), @@ -1207,16 +1207,16 @@ public final class Cea708Decoder extends CeaDecoder { rolledUpCaptions.add(buildSpannableString()); captionStringBuilder.clear(); - if (italicsStartPosition != C.POSITION_UNSET) { + if (italicsStartPosition != C.INDEX_UNSET) { italicsStartPosition = 0; } - if (underlineStartPosition != C.POSITION_UNSET) { + if (underlineStartPosition != C.INDEX_UNSET) { underlineStartPosition = 0; } - if (foregroundColorStartPosition != C.POSITION_UNSET) { + if (foregroundColorStartPosition != C.INDEX_UNSET) { foregroundColorStartPosition = 0; } - if (backgroundColorStartPosition != C.POSITION_UNSET) { + if (backgroundColorStartPosition != C.INDEX_UNSET) { backgroundColorStartPosition = 0; } @@ -1235,7 +1235,7 @@ public final class Cea708Decoder extends CeaDecoder { int length = spannableStringBuilder.length(); if (length > 0) { - if (italicsStartPosition != C.POSITION_UNSET) { + if (italicsStartPosition != C.INDEX_UNSET) { spannableStringBuilder.setSpan( new StyleSpan(Typeface.ITALIC), italicsStartPosition, @@ -1243,7 +1243,7 @@ public final class Cea708Decoder extends CeaDecoder { Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - if (underlineStartPosition != C.POSITION_UNSET) { + if (underlineStartPosition != C.INDEX_UNSET) { spannableStringBuilder.setSpan( new UnderlineSpan(), underlineStartPosition, @@ -1251,7 +1251,7 @@ public final class Cea708Decoder extends CeaDecoder { Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - if (foregroundColorStartPosition != C.POSITION_UNSET) { + if (foregroundColorStartPosition != C.INDEX_UNSET) { spannableStringBuilder.setSpan( new ForegroundColorSpan(foregroundColor), foregroundColorStartPosition, @@ -1259,7 +1259,7 @@ public final class Cea708Decoder extends CeaDecoder { Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - if (backgroundColorStartPosition != C.POSITION_UNSET) { + if (backgroundColorStartPosition != C.INDEX_UNSET) { spannableStringBuilder.setSpan( new BackgroundColorSpan(backgroundColor), backgroundColorStartPosition, 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 dea5d20ad9..4d9d17c647 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 @@ -218,7 +218,7 @@ public final class PsExtractorSeekTest { long initialSeekLoadPosition = seekPoints.first.position; psExtractor.seek(initialSeekLoadPosition, seekTimeUs); - positionHolder.position = C.POSITION_UNSET; + positionHolder.position = C.INDEX_UNSET; ExtractorInput extractorInput = getExtractorInputFromPosition(initialSeekLoadPosition); int extractorReadResult = Extractor.RESULT_CONTINUE; while (true) { diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java index 18bed1670a..bd85f4eaea 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java @@ -426,7 +426,7 @@ public class TestUtil { extractor.seek(initialSeekLoadPosition, seekTimeUs); PositionHolder positionHolder = new PositionHolder(); - positionHolder.position = C.POSITION_UNSET; + positionHolder.position = C.INDEX_UNSET; ExtractorInput extractorInput = TestUtil.getExtractorInputFromPosition(dataSource, initialSeekLoadPosition, uri); int extractorReadResult = Extractor.RESULT_CONTINUE; From f3832b33d36cda9aa1099a8597209a261fb97d5f Mon Sep 17 00:00:00 2001 From: Googler Date: Fri, 2 Dec 2022 23:55:10 +0000 Subject: [PATCH 047/183] Temporal fix to allow proper library shrinking. PiperOrigin-RevId: 492579961 --- .../exoplayer2/extractor/DefaultExtractorsFactory.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 1933c93803..2f9e6bc4df 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 @@ -128,13 +128,13 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory { private @Mp3Extractor.Flags int mp3Flags; private @TsExtractor.Mode int tsMode; private @DefaultTsPayloadReaderFactory.Flags int tsFlags; - private ImmutableList tsSubtitleFormats; + // TODO (b/260245332): Initialize tsSubtitleFormats in constructor once shrinking bug is fixed. + @Nullable private ImmutableList tsSubtitleFormats; private int tsTimestampSearchBytes; public DefaultExtractorsFactory() { tsMode = TsExtractor.MODE_SINGLE_PMT; tsTimestampSearchBytes = TsExtractor.DEFAULT_TIMESTAMP_SEARCH_BYTES; - tsSubtitleFormats = ImmutableList.of(); } /** @@ -432,6 +432,9 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory { extractors.add(new PsExtractor()); break; case FileTypes.TS: + if (tsSubtitleFormats == null) { + tsSubtitleFormats = ImmutableList.of(); + } extractors.add( new TsExtractor( tsMode, From 589b4a177b0431fff505a112b6acdc44cf2d831b Mon Sep 17 00:00:00 2001 From: samrobinson Date: Mon, 5 Dec 2022 14:50:03 +0000 Subject: [PATCH 048/183] Add force silent audio to the transformer demo application. Adds a modified version of sample.mp4 to the list, which has no audio. PiperOrigin-RevId: 492993918 --- .../ConfigurationActivity.java | 22 ++++++++++++++----- .../transformerdemo/TransformerActivity.java | 2 ++ .../res/layout/configuration_activity.xml | 9 ++++++++ .../src/main/res/values/strings.xml | 1 + 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java index 0837c98f47..9e5bad8eb0 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java @@ -59,6 +59,7 @@ public final class ConfigurationActivity extends AppCompatActivity { public static final String SHOULD_REMOVE_AUDIO = "should_remove_audio"; public static final String SHOULD_REMOVE_VIDEO = "should_remove_video"; public static final String SHOULD_FLATTEN_FOR_SLOW_MOTION = "should_flatten_for_slow_motion"; + public static final String FORCE_SILENT_AUDIO = "force_silent_audio"; public static final String AUDIO_MIME_TYPE = "audio_mime_type"; public static final String VIDEO_MIME_TYPE = "video_mime_type"; public static final String RESOLUTION_HEIGHT = "resolution_height"; @@ -103,6 +104,7 @@ public final class ConfigurationActivity extends AppCompatActivity { "https://storage.googleapis.com/exoplayer-test-media-1/gen/screens/dash-vod-single-segment/manifest-baseline.mpd", "https://storage.googleapis.com/exoplayer-test-media-1/mp4/samsung-s21-hdr-hdr10.mp4", "https://storage.googleapis.com/exoplayer-test-media-1/mp4/Pixel7Pro_HLG_1080P.mp4", + "https://storage.googleapis.com/exoplayer-test-media-1/mp4/sample_video_track_only.mp4", }; private static final String[] PRESET_FILE_URI_DESCRIPTIONS = { // same order as PRESET_FILE_URIS "720p H264 video and AAC audio", @@ -119,6 +121,7 @@ public final class ConfigurationActivity extends AppCompatActivity { "480p DASH (non-square pixels)", "HDR (HDR10) H265 limited range video (encoding may fail)", "HDR (HLG) H265 limited range video (encoding may fail)", + "720p H264 video with no audio", }; private static final String[] DEMO_EFFECTS = { "Dizzy crop", @@ -157,6 +160,7 @@ public final class ConfigurationActivity extends AppCompatActivity { private @MonotonicNonNull CheckBox removeAudioCheckbox; private @MonotonicNonNull CheckBox removeVideoCheckbox; private @MonotonicNonNull CheckBox flattenForSlowMotionCheckbox; + private @MonotonicNonNull CheckBox forceSilentAudioCheckbox; private @MonotonicNonNull Spinner audioMimeSpinner; private @MonotonicNonNull Spinner videoMimeSpinner; private @MonotonicNonNull Spinner resolutionHeightSpinner; @@ -193,7 +197,11 @@ public final class ConfigurationActivity extends AppCompatActivity { findViewById(R.id.transform_button).setOnClickListener(this::startTransformation); - flattenForSlowMotionCheckbox = findViewById(R.id.flatten_for_slow_motion_checkbox); + selectPresetFileButton = findViewById(R.id.select_preset_file_button); + selectPresetFileButton.setOnClickListener(this::selectPresetFile); + + selectLocalFileButton = findViewById(R.id.select_local_file_button); + selectLocalFileButton.setOnClickListener(this::selectLocalFile); selectedFileTextView = findViewById(R.id.selected_file_text_view); selectedFileTextView.setText(PRESET_FILE_URI_DESCRIPTIONS[inputUriPosition]); @@ -204,11 +212,9 @@ public final class ConfigurationActivity extends AppCompatActivity { removeVideoCheckbox = findViewById(R.id.remove_video_checkbox); removeVideoCheckbox.setOnClickListener(this::onRemoveVideo); - selectPresetFileButton = findViewById(R.id.select_preset_file_button); - selectPresetFileButton.setOnClickListener(this::selectPresetFile); + flattenForSlowMotionCheckbox = findViewById(R.id.flatten_for_slow_motion_checkbox); - selectLocalFileButton = findViewById(R.id.select_local_file_button); - selectLocalFileButton.setOnClickListener(this::selectLocalFile); + forceSilentAudioCheckbox = findViewById(R.id.force_silent_audio_checkbox); ArrayAdapter audioMimeAdapter = new ArrayAdapter<>(/* context= */ this, R.layout.spinner_item); @@ -315,6 +321,7 @@ public final class ConfigurationActivity extends AppCompatActivity { "removeAudioCheckbox", "removeVideoCheckbox", "flattenForSlowMotionCheckbox", + "forceSilentAudioCheckbox", "audioMimeSpinner", "videoMimeSpinner", "resolutionHeightSpinner", @@ -333,6 +340,7 @@ public final class ConfigurationActivity extends AppCompatActivity { bundle.putBoolean(SHOULD_REMOVE_AUDIO, removeAudioCheckbox.isChecked()); bundle.putBoolean(SHOULD_REMOVE_VIDEO, removeVideoCheckbox.isChecked()); bundle.putBoolean(SHOULD_FLATTEN_FOR_SLOW_MOTION, flattenForSlowMotionCheckbox.isChecked()); + bundle.putBoolean(FORCE_SILENT_AUDIO, forceSilentAudioCheckbox.isChecked()); String selectedAudioMimeType = String.valueOf(audioMimeSpinner.getSelectedItem()); if (!SAME_AS_INPUT_OPTION.equals(selectedAudioMimeType)) { bundle.putString(AUDIO_MIME_TYPE, selectedAudioMimeType); @@ -596,6 +604,7 @@ public final class ConfigurationActivity extends AppCompatActivity { @RequiresNonNull({ "removeVideoCheckbox", + "forceSilentAudioCheckbox", "audioMimeSpinner", "videoMimeSpinner", "resolutionHeightSpinner", @@ -616,6 +625,7 @@ public final class ConfigurationActivity extends AppCompatActivity { @RequiresNonNull({ "removeAudioCheckbox", + "forceSilentAudioCheckbox", "audioMimeSpinner", "videoMimeSpinner", "resolutionHeightSpinner", @@ -635,6 +645,7 @@ public final class ConfigurationActivity extends AppCompatActivity { } @RequiresNonNull({ + "forceSilentAudioCheckbox", "audioMimeSpinner", "videoMimeSpinner", "resolutionHeightSpinner", @@ -645,6 +656,7 @@ public final class ConfigurationActivity extends AppCompatActivity { "selectDemoEffectsButton" }) private void enableTrackSpecificOptions(boolean isAudioEnabled, boolean isVideoEnabled) { + forceSilentAudioCheckbox.setEnabled(isVideoEnabled); audioMimeSpinner.setEnabled(isAudioEnabled); videoMimeSpinner.setEnabled(isVideoEnabled); resolutionHeightSpinner.setEnabled(isVideoEnabled); diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java index c780e6e3ac..caaa06f796 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java @@ -276,6 +276,8 @@ public final class TransformerActivity extends AppCompatActivity { .setTransformationRequest(requestBuilder.build()) .setRemoveAudio(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_AUDIO)) .setRemoveVideo(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_VIDEO)) + .experimentalSetForceSilentAudio( + bundle.getBoolean(ConfigurationActivity.FORCE_SILENT_AUDIO)) .setEncoderFactory( new DefaultEncoderFactory.Builder(this.getApplicationContext()) .setEnableFallback(bundle.getBoolean(ConfigurationActivity.ENABLE_FALLBACK)) diff --git a/demos/transformer/src/main/res/layout/configuration_activity.xml b/demos/transformer/src/main/res/layout/configuration_activity.xml index f78f57fee9..6147aa07f2 100644 --- a/demos/transformer/src/main/res/layout/configuration_activity.xml +++ b/demos/transformer/src/main/res/layout/configuration_activity.xml @@ -112,6 +112,15 @@ android:id="@+id/flatten_for_slow_motion_checkbox" android:layout_gravity="end" /> + + + + diff --git a/demos/transformer/src/main/res/values/strings.xml b/demos/transformer/src/main/res/values/strings.xml index 0e4fb6e739..99dd79171a 100644 --- a/demos/transformer/src/main/res/values/strings.xml +++ b/demos/transformer/src/main/res/values/strings.xml @@ -65,4 +65,5 @@ Permission Denied Hide input video Show input video + Force silent audio From 8d5fe8fec941b08715f1b324696416673c56d208 Mon Sep 17 00:00:00 2001 From: samrobinson Date: Mon, 5 Dec 2022 15:28:09 +0000 Subject: [PATCH 049/183] Add setter for some audio effects to demo app. PiperOrigin-RevId: 493001630 --- .../ConfigurationActivity.java | 69 ++++++++++++++----- .../transformerdemo/TransformerActivity.java | 45 +++++++++++- .../res/layout/configuration_activity.xml | 17 ++++- .../src/main/res/values/strings.xml | 3 +- 4 files changed, 108 insertions(+), 26 deletions(-) diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java index 9e5bad8eb0..5ab9344bce 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java @@ -72,7 +72,8 @@ public final class ConfigurationActivity extends AppCompatActivity { public static final String ENABLE_DEBUG_PREVIEW = "enable_debug_preview"; public static final String ABORT_SLOW_TRANSFORMATION = "abort_slow_transformation"; public static final String HDR_MODE = "hdr_mode"; - public static final String DEMO_EFFECTS_SELECTIONS = "demo_effects_selections"; + public static final String AUDIO_EFFECTS_SELECTIONS = "audio_effects_selections"; + public static final String VIDEO_EFFECTS_SELECTIONS = "video_effects_selections"; public static final String PERIODIC_VIGNETTE_CENTER_X = "periodic_vignette_center_x"; public static final String PERIODIC_VIGNETTE_CENTER_Y = "periodic_vignette_center_y"; public static final String PERIODIC_VIGNETTE_INNER_RADIUS = "periodic_vignette_inner_radius"; @@ -123,7 +124,10 @@ public final class ConfigurationActivity extends AppCompatActivity { "HDR (HLG) H265 limited range video (encoding may fail)", "720p H264 video with no audio", }; - private static final String[] DEMO_EFFECTS = { + private static final String[] AUDIO_EFFECTS = { + "High pitched", "Sample rate of 48000Hz", "Skip silence" + }; + private static final String[] VIDEO_EFFECTS = { "Dizzy crop", "Edge detector (Media Pipe)", "Color filters", @@ -171,8 +175,10 @@ public final class ConfigurationActivity extends AppCompatActivity { private @MonotonicNonNull CheckBox enableDebugPreviewCheckBox; private @MonotonicNonNull CheckBox abortSlowTransformationCheckBox; private @MonotonicNonNull Spinner hdrModeSpinner; - private @MonotonicNonNull Button selectDemoEffectsButton; - private boolean @MonotonicNonNull [] demoEffectsSelections; + private @MonotonicNonNull Button selectAudioEffectsButton; + private @MonotonicNonNull Button selectVideoEffectsButton; + private boolean @MonotonicNonNull [] audioEffectsSelections; + private boolean @MonotonicNonNull [] videoEffectsSelections; private @Nullable Uri localFileUri; private int inputUriPosition; private long trimStartMs; @@ -274,9 +280,13 @@ public final class ConfigurationActivity extends AppCompatActivity { hdrModeSpinner.setAdapter(hdrModeAdapter); hdrModeAdapter.addAll(HDR_MODE_DESCRIPTIONS.keySet()); - demoEffectsSelections = new boolean[DEMO_EFFECTS.length]; - selectDemoEffectsButton = findViewById(R.id.select_demo_effects_button); - selectDemoEffectsButton.setOnClickListener(this::selectDemoEffects); + audioEffectsSelections = new boolean[AUDIO_EFFECTS.length]; + selectAudioEffectsButton = findViewById(R.id.select_audio_effects_button); + selectAudioEffectsButton.setOnClickListener(this::selectAudioEffects); + + videoEffectsSelections = new boolean[VIDEO_EFFECTS.length]; + selectVideoEffectsButton = findViewById(R.id.select_video_effects_button); + selectVideoEffectsButton.setOnClickListener(this::selectVideoEffects); localFilePickerLauncher = registerForActivityResult( @@ -332,7 +342,8 @@ public final class ConfigurationActivity extends AppCompatActivity { "enableDebugPreviewCheckBox", "abortSlowTransformationCheckBox", "hdrModeSpinner", - "demoEffectsSelections" + "audioEffectsSelections", + "videoEffectsSelections" }) private void startTransformation(View view) { Intent transformerIntent = new Intent(/* packageContext= */ this, TransformerActivity.class); @@ -373,7 +384,8 @@ public final class ConfigurationActivity extends AppCompatActivity { bundle.putBoolean(ABORT_SLOW_TRANSFORMATION, abortSlowTransformationCheckBox.isChecked()); String selectedhdrMode = String.valueOf(hdrModeSpinner.getSelectedItem()); bundle.putInt(HDR_MODE, checkNotNull(HDR_MODE_DESCRIPTIONS.get(selectedhdrMode))); - bundle.putBooleanArray(DEMO_EFFECTS_SELECTIONS, demoEffectsSelections); + bundle.putBooleanArray(AUDIO_EFFECTS_SELECTIONS, audioEffectsSelections); + bundle.putBooleanArray(VIDEO_EFFECTS_SELECTIONS, videoEffectsSelections); bundle.putInt(COLOR_FILTER_SELECTION, colorFilterSelection); bundle.putFloat(CONTRAST_VALUE, contrastValue); bundle.putFloat(RGB_ADJUSTMENT_RED_SCALE, rgbAdjustmentRedScale); @@ -446,11 +458,21 @@ public final class ConfigurationActivity extends AppCompatActivity { } } - private void selectDemoEffects(View view) { + private void selectAudioEffects(View view) { new AlertDialog.Builder(/* context= */ this) - .setTitle(R.string.select_demo_effects) + .setTitle(R.string.select_audio_effects) .setMultiChoiceItems( - DEMO_EFFECTS, checkNotNull(demoEffectsSelections), this::selectDemoEffect) + AUDIO_EFFECTS, checkNotNull(audioEffectsSelections), this::selectAudioEffect) + .setPositiveButton(android.R.string.ok, /* listener= */ null) + .create() + .show(); + } + + private void selectVideoEffects(View view) { + new AlertDialog.Builder(/* context= */ this) + .setTitle(R.string.select_video_effects) + .setMultiChoiceItems( + VIDEO_EFFECTS, checkNotNull(videoEffectsSelections), this::selectVideoEffect) .setPositiveButton(android.R.string.ok, /* listener= */ null) .create() .show(); @@ -477,9 +499,14 @@ public final class ConfigurationActivity extends AppCompatActivity { .show(); } - @RequiresNonNull("demoEffectsSelections") - private void selectDemoEffect(DialogInterface dialog, int which, boolean isChecked) { - demoEffectsSelections[which] = isChecked; + @RequiresNonNull("audioEffectsSelections") + private void selectAudioEffect(DialogInterface dialog, int which, boolean isChecked) { + audioEffectsSelections[which] = isChecked; + } + + @RequiresNonNull("videoEffectsSelections") + private void selectVideoEffect(DialogInterface dialog, int which, boolean isChecked) { + videoEffectsSelections[which] = isChecked; if (!isChecked) { return; } @@ -612,7 +639,8 @@ public final class ConfigurationActivity extends AppCompatActivity { "rotateSpinner", "enableDebugPreviewCheckBox", "hdrModeSpinner", - "selectDemoEffectsButton" + "selectAudioEffectsButton", + "selectVideoEffectsButton" }) private void onRemoveAudio(View view) { if (((CheckBox) view).isChecked()) { @@ -633,7 +661,8 @@ public final class ConfigurationActivity extends AppCompatActivity { "rotateSpinner", "enableDebugPreviewCheckBox", "hdrModeSpinner", - "selectDemoEffectsButton" + "selectAudioEffectsButton", + "selectVideoEffectsButton" }) private void onRemoveVideo(View view) { if (((CheckBox) view).isChecked()) { @@ -653,7 +682,8 @@ public final class ConfigurationActivity extends AppCompatActivity { "rotateSpinner", "enableDebugPreviewCheckBox", "hdrModeSpinner", - "selectDemoEffectsButton" + "selectAudioEffectsButton", + "selectVideoEffectsButton" }) private void enableTrackSpecificOptions(boolean isAudioEnabled, boolean isVideoEnabled) { forceSilentAudioCheckbox.setEnabled(isVideoEnabled); @@ -664,7 +694,8 @@ public final class ConfigurationActivity extends AppCompatActivity { rotateSpinner.setEnabled(isVideoEnabled); enableDebugPreviewCheckBox.setEnabled(isVideoEnabled); hdrModeSpinner.setEnabled(isVideoEnabled); - selectDemoEffectsButton.setEnabled(isVideoEnabled); + selectAudioEffectsButton.setEnabled(isAudioEnabled); + selectVideoEffectsButton.setEnabled(isVideoEnabled); findViewById(R.id.audio_mime_text_view).setEnabled(isAudioEnabled); findViewById(R.id.video_mime_text_view).setEnabled(isVideoEnabled); diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java index caaa06f796..ed071a505f 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java @@ -40,6 +40,9 @@ import androidx.appcompat.app.AppCompatActivity; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.audio.AudioProcessor; +import com.google.android.exoplayer2.audio.SilenceSkippingAudioProcessor; +import com.google.android.exoplayer2.audio.SonicAudioProcessor; import com.google.android.exoplayer2.effect.Contrast; import com.google.android.exoplayer2.effect.GlEffect; import com.google.android.exoplayer2.effect.GlTextureProcessor; @@ -283,7 +286,8 @@ public final class TransformerActivity extends AppCompatActivity { .setEnableFallback(bundle.getBoolean(ConfigurationActivity.ENABLE_FALLBACK)) .build()); - transformerBuilder.setVideoEffects(createVideoEffectsListFromBundle(bundle)); + transformerBuilder.setAudioProcessors(createAudioProcessorsFromBundle(bundle)); + transformerBuilder.setVideoEffects(createVideoEffectsFromBundle(bundle)); if (bundle.getBoolean(ConfigurationActivity.ENABLE_DEBUG_PREVIEW)) { transformerBuilder.setDebugViewProvider(new DemoDebugViewProvider()); @@ -325,10 +329,45 @@ public final class TransformerActivity extends AppCompatActivity { return file; } - private ImmutableList createVideoEffectsListFromBundle(Bundle bundle) { + private ImmutableList createAudioProcessorsFromBundle(Bundle bundle) { + @Nullable + boolean[] selectedAudioEffects = + bundle.getBooleanArray(ConfigurationActivity.AUDIO_EFFECTS_SELECTIONS); + + if (selectedAudioEffects == null) { + return ImmutableList.of(); + } + + ImmutableList.Builder processors = new ImmutableList.Builder<>(); + + if (selectedAudioEffects[0] || selectedAudioEffects[1]) { + SonicAudioProcessor sonicAudioProcessor = new SonicAudioProcessor(); + // High pitched + if (selectedAudioEffects[0]) { + sonicAudioProcessor.setPitch(2f); + } + // 48KHz sample rate. + if (selectedAudioEffects[1]) { + sonicAudioProcessor.setOutputSampleRateHz(48_000); + } + processors.add(sonicAudioProcessor); + } + + // Skip silence + if (selectedAudioEffects[2]) { + SilenceSkippingAudioProcessor silenceSkippingAudioProcessor = + new SilenceSkippingAudioProcessor(); + silenceSkippingAudioProcessor.setEnabled(true); + processors.add(silenceSkippingAudioProcessor); + } + + return processors.build(); + } + + private ImmutableList createVideoEffectsFromBundle(Bundle bundle) { @Nullable boolean[] selectedEffects = - bundle.getBooleanArray(ConfigurationActivity.DEMO_EFFECTS_SELECTIONS); + bundle.getBooleanArray(ConfigurationActivity.VIDEO_EFFECTS_SELECTIONS); if (selectedEffects == null) { return ImmutableList.of(); } diff --git a/demos/transformer/src/main/res/layout/configuration_activity.xml b/demos/transformer/src/main/res/layout/configuration_activity.xml index 6147aa07f2..09aa1287d1 100644 --- a/demos/transformer/src/main/res/layout/configuration_activity.xml +++ b/demos/transformer/src/main/res/layout/configuration_activity.xml @@ -75,7 +75,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/selected_file_text_view" - app:layout_constraintBottom_toTopOf="@+id/select_demo_effects_button"> + app:layout_constraintBottom_toTopOf="@+id/select_audio_effects_button">