From efaf4e3f3375748c8f988f2904bf77a7f829b887 Mon Sep 17 00:00:00 2001 From: tofunmi Date: Fri, 3 Mar 2023 15:40:38 +0000 Subject: [PATCH] Remove effect/SimpleBitmapLoader & replace with DataSourceBitmapLoader PiperOrigin-RevId: 513824487 --- .../demo/transformer/TransformerActivity.java | 4 +- libraries/effect/build.gradle | 1 + .../androidx/media3/effect/BitmapOverlay.java | 8 +- .../media3/effect/SimpleBitmapLoader.java | 122 ------------------ libraries/transformer/build.gradle | 1 + .../DefaultAssetLoaderFactory.java | 6 +- .../media3/transformer/ImageAssetLoader.java | 17 ++- 7 files changed, 27 insertions(+), 132 deletions(-) delete mode 100644 libraries/effect/src/main/java/androidx/media3/effect/SimpleBitmapLoader.java diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java index 5bd5903a1b..64492380bc 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java @@ -58,6 +58,7 @@ import androidx.media3.common.audio.SonicAudioProcessor; import androidx.media3.common.util.BitmapLoader; import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.Log; +import androidx.media3.datasource.DataSourceBitmapLoader; import androidx.media3.effect.BitmapOverlay; import androidx.media3.effect.Contrast; import androidx.media3.effect.DrawableOverlay; @@ -71,7 +72,6 @@ import androidx.media3.effect.RgbAdjustment; import androidx.media3.effect.RgbFilter; import androidx.media3.effect.RgbMatrix; import androidx.media3.effect.ScaleAndRotateTransformation; -import androidx.media3.effect.SimpleBitmapLoader; import androidx.media3.effect.SingleColorLut; import androidx.media3.effect.TextOverlay; import androidx.media3.effect.TextureOverlay; @@ -690,7 +690,7 @@ public final class TransformerActivity extends AppCompatActivity { inputImageView.setVisibility(View.VISIBLE); inputTextView.setText(getString(R.string.input_image)); - BitmapLoader bitmapLoader = new SimpleBitmapLoader(); + BitmapLoader bitmapLoader = new DataSourceBitmapLoader(getApplicationContext()); ListenableFuture future = bitmapLoader.loadBitmap(uri); try { Bitmap bitmap = future.get(); diff --git a/libraries/effect/build.gradle b/libraries/effect/build.gradle index e3e319a801..cbcdc089af 100644 --- a/libraries/effect/build.gradle +++ b/libraries/effect/build.gradle @@ -38,6 +38,7 @@ android { dependencies { implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion implementation project(modulePrefix + 'lib-common') + implementation project(modulePrefix + 'lib-datasource') compileOnly 'com.google.errorprone:error_prone_annotations:' + errorProneVersion compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion compileOnly 'org.checkerframework:checker-compat-qual:' + checkerframeworkCompatVersion diff --git a/libraries/effect/src/main/java/androidx/media3/effect/BitmapOverlay.java b/libraries/effect/src/main/java/androidx/media3/effect/BitmapOverlay.java index a72b3c8e0f..720b8d3477 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/BitmapOverlay.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/BitmapOverlay.java @@ -16,6 +16,7 @@ package androidx.media3.effect; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Assertions.checkStateNotNull; import android.graphics.Bitmap; import android.net.Uri; @@ -26,6 +27,8 @@ import androidx.media3.common.util.BitmapLoader; import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.Size; import androidx.media3.common.util.UnstableApi; +import androidx.media3.datasource.DataSourceBitmapLoader; +import androidx.media3.datasource.DefaultHttpDataSource; import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.ExecutionException; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -136,7 +139,10 @@ public abstract class BitmapOverlay extends TextureOverlay { @Override public Bitmap getBitmap(long presentationTimeUs) throws VideoFrameProcessingException { if (lastBitmap == null) { - BitmapLoader bitmapLoader = new SimpleBitmapLoader(); + BitmapLoader bitmapLoader = + new DataSourceBitmapLoader( + checkStateNotNull(DataSourceBitmapLoader.DEFAULT_EXECUTOR_SERVICE.get()), + new DefaultHttpDataSource.Factory()); ListenableFuture future = bitmapLoader.loadBitmap(overlayBitmapUri); try { lastBitmap = future.get(); diff --git a/libraries/effect/src/main/java/androidx/media3/effect/SimpleBitmapLoader.java b/libraries/effect/src/main/java/androidx/media3/effect/SimpleBitmapLoader.java deleted file mode 100644 index ca89666cfd..0000000000 --- a/libraries/effect/src/main/java/androidx/media3/effect/SimpleBitmapLoader.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ -package androidx.media3.effect; - -import static androidx.media3.common.util.Assertions.checkArgument; -import static androidx.media3.common.util.Assertions.checkStateNotNull; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import androidx.annotation.Nullable; -import androidx.media3.common.util.BitmapLoader; -import androidx.media3.common.util.UnstableApi; -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. - */ -@UnstableApi -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/libraries/transformer/build.gradle b/libraries/transformer/build.gradle index d5f1a8e581..6038fbb26e 100644 --- a/libraries/transformer/build.gradle +++ b/libraries/transformer/build.gradle @@ -37,6 +37,7 @@ android { dependencies { implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion + implementation project(modulePrefix + 'lib-datasource') implementation project(modulePrefix + 'lib-exoplayer') implementation project(modulePrefix + 'lib-effect') compileOnly 'com.google.errorprone:error_prone_annotations:' + errorProneVersion diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultAssetLoaderFactory.java b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultAssetLoaderFactory.java index 8fa9ebe654..10ea97fa94 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultAssetLoaderFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultAssetLoaderFactory.java @@ -56,7 +56,7 @@ public final class DefaultAssetLoaderFactory implements AssetLoader.Factory { Codec.DecoderFactory decoderFactory, boolean forceInterpretHdrAsSdr, Clock clock) { - this.context = context; + this.context = context.getApplicationContext(); this.decoderFactory = decoderFactory; this.forceInterpretHdrAsSdr = forceInterpretHdrAsSdr; this.clock = clock; @@ -82,7 +82,7 @@ public final class DefaultAssetLoaderFactory implements AssetLoader.Factory { boolean forceInterpretHdrAsSdr, Clock clock, MediaSource.Factory mediaSourceFactory) { - this.context = context; + this.context = context.getApplicationContext(); this.decoderFactory = decoderFactory; this.forceInterpretHdrAsSdr = forceInterpretHdrAsSdr; this.clock = clock; @@ -95,7 +95,7 @@ public final class DefaultAssetLoaderFactory implements AssetLoader.Factory { MediaItem mediaItem = editedMediaItem.mediaItem; if (isImage(mediaItem.localConfiguration)) { if (imageAssetLoaderFactory == null) { - imageAssetLoaderFactory = new ImageAssetLoader.Factory(); + imageAssetLoaderFactory = new ImageAssetLoader.Factory(context); } return imageAssetLoaderFactory.createAssetLoader(editedMediaItem, looper, listener); } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ImageAssetLoader.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ImageAssetLoader.java index d1e52881d7..b5ee7e6fcf 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ImageAssetLoader.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ImageAssetLoader.java @@ -23,6 +23,7 @@ import static androidx.media3.transformer.ExportException.ERROR_CODE_UNSPECIFIED import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED; +import android.content.Context; import android.graphics.Bitmap; import android.os.Looper; import androidx.media3.common.C; @@ -31,7 +32,7 @@ import androidx.media3.common.MediaItem; import androidx.media3.common.MimeTypes; import androidx.media3.common.util.BitmapLoader; import androidx.media3.common.util.UnstableApi; -import androidx.media3.effect.SimpleBitmapLoader; +import androidx.media3.datasource.DataSourceBitmapLoader; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -45,22 +46,30 @@ public final class ImageAssetLoader implements AssetLoader { /** An {@link AssetLoader.Factory} for {@link ImageAssetLoader} instances. */ public static final class Factory implements AssetLoader.Factory { + private final Context context; + + public Factory(Context context) { + this.context = context.getApplicationContext(); + } + @Override public AssetLoader createAssetLoader( EditedMediaItem editedMediaItem, Looper looper, Listener listener) { - return new ImageAssetLoader(editedMediaItem, listener); + return new ImageAssetLoader(context, editedMediaItem, listener); } } public static final String MIME_TYPE_IMAGE_ALL = MimeTypes.BASE_TYPE_IMAGE + "/*"; + private final Context context; private final EditedMediaItem editedMediaItem; private final Listener listener; private @Transformer.ProgressState int progressState; private int progress; - private ImageAssetLoader(EditedMediaItem editedMediaItem, Listener listener) { + private ImageAssetLoader(Context context, EditedMediaItem editedMediaItem, Listener listener) { + this.context = context; this.editedMediaItem = editedMediaItem; this.listener = listener; @@ -71,7 +80,7 @@ public final class ImageAssetLoader implements AssetLoader { public void start() { progressState = PROGRESS_STATE_AVAILABLE; listener.onTrackCount(1); - BitmapLoader bitmapLoader = new SimpleBitmapLoader(); + BitmapLoader bitmapLoader = new DataSourceBitmapLoader(context); MediaItem.LocalConfiguration localConfiguration = checkNotNull(editedMediaItem.mediaItem.localConfiguration); ListenableFuture future = bitmapLoader.loadBitmap(localConfiguration.uri);