From 72ba3554a97d8ad51400aa858e4cabd2b88ec9a8 Mon Sep 17 00:00:00 2001 From: kimvde Date: Wed, 22 May 2024 01:38:59 -0700 Subject: [PATCH] Set image duration on all media types This was previously only set on images because it was not ignored on other media types. This parameter was made no-op for non-images in https://github.com/androidx/media/commit/7b2a1b444312953f9518868f1cfc3e0b6c400d7b. PiperOrigin-RevId: 636078142 --- .../CompositionPreviewActivity.java | 14 ++- .../DefaultAssetLoaderFactory.java | 55 +++++++++++- .../media3/transformer/ImageUtil.java | 85 ------------------- 3 files changed, 58 insertions(+), 96 deletions(-) delete mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/ImageUtil.java diff --git a/demos/composition/src/main/java/androidx/media3/demo/composition/CompositionPreviewActivity.java b/demos/composition/src/main/java/androidx/media3/demo/composition/CompositionPreviewActivity.java index 5c46c5c53a..cff9f32e21 100644 --- a/demos/composition/src/main/java/androidx/media3/demo/composition/CompositionPreviewActivity.java +++ b/demos/composition/src/main/java/androidx/media3/demo/composition/CompositionPreviewActivity.java @@ -18,11 +18,9 @@ package androidx.media3.demo.composition; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkStateNotNull; -import static androidx.media3.transformer.ImageUtil.getCommonImageMimeTypeFromExtension; import android.app.Activity; import android.content.DialogInterface; -import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Toast; @@ -33,7 +31,6 @@ import androidx.appcompat.widget.AppCompatButton; import androidx.appcompat.widget.AppCompatTextView; import androidx.media3.common.Effect; import androidx.media3.common.MediaItem; -import androidx.media3.common.MimeTypes; import androidx.media3.common.PlaybackException; import androidx.media3.common.Player; import androidx.media3.common.audio.SonicAudioProcessor; @@ -163,14 +160,13 @@ public final class CompositionPreviewActivity extends AppCompatActivity { MatrixTransformationFactory.createDizzyCropEffect(), RgbFilter.createGrayscaleFilter()); for (int i = 0; i < checkNotNull(selectedMediaItems).length; i++) { if (checkNotNull(selectedMediaItems)[i]) { - Uri uri = Uri.parse(presetFileUris[i]); - MediaItem.Builder mediaItemBuilder = new MediaItem.Builder().setUri(uri); - if (MimeTypes.isImage(getCommonImageMimeTypeFromExtension(uri))) { - mediaItemBuilder.setImageDurationMs(Util.usToMs(presetDurationsUs[i])); - } - MediaItem mediaItem = mediaItemBuilder.build(); SonicAudioProcessor pitchChanger = new SonicAudioProcessor(); pitchChanger.setPitch(mediaItems.size() % 2 == 0 ? 2f : 0.2f); + MediaItem mediaItem = + new MediaItem.Builder() + .setUri(presetFileUris[i]) + .setImageDurationMs(Util.usToMs(presetDurationsUs[i])) // Ignored for audio/video + .build(); EditedMediaItem.Builder itemBuilder = new EditedMediaItem.Builder(mediaItem) .setEffects( 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 4fbb243c40..5220dc7748 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultAssetLoaderFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultAssetLoaderFactory.java @@ -17,7 +17,6 @@ package androidx.media3.transformer; import static androidx.media3.common.util.Assertions.checkState; -import static androidx.media3.transformer.ImageUtil.getCommonImageMimeTypeFromExtension; import android.content.ContentResolver; import android.content.Context; @@ -35,6 +34,7 @@ import androidx.media3.datasource.DataSourceBitmapLoader; import androidx.media3.datasource.DefaultDataSource; import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.transformer.AssetLoader.CompositionSettings; +import com.google.common.base.Ascii; import com.google.common.util.concurrent.MoreExecutors; import java.util.Objects; import java.util.concurrent.Executors; @@ -160,7 +160,15 @@ public final class DefaultAssetLoaderFactory implements AssetLoader.Factory { ContentResolver cr = context.getContentResolver(); mimeType = cr.getType(localConfiguration.uri); } else { - mimeType = getCommonImageMimeTypeFromExtension(localConfiguration.uri); + @Nullable String uriPath = localConfiguration.uri.getPath(); + if (uriPath == null) { + return false; + } + int fileExtensionStart = uriPath.lastIndexOf("."); + if (fileExtensionStart >= 0 && fileExtensionStart < uriPath.length() - 1) { + String extension = Ascii.toLowerCase(uriPath.substring(fileExtensionStart + 1)); + mimeType = getCommonImageMimeTypeFromExtension(extension); + } } } if (mimeType == null) { @@ -174,4 +182,47 @@ public final class DefaultAssetLoaderFactory implements AssetLoader.Factory { "Image format not supported by given bitmapLoader"); return true; } + + @Nullable + private static String getCommonImageMimeTypeFromExtension(String extension) { + switch (extension) { + case "bmp": + case "dib": + return MimeTypes.IMAGE_BMP; + case "heif": + return MimeTypes.IMAGE_HEIF; + case "heic": + return MimeTypes.IMAGE_HEIC; + case "jpg": + case "jpeg": + case "jpe": + case "jif": + case "jfif": + case "jfi": + return MimeTypes.IMAGE_JPEG; + case "png": + return MimeTypes.IMAGE_PNG; + case "webp": + return MimeTypes.IMAGE_WEBP; + case "gif": + return "image/gif"; + case "tiff": + case "tif": + return "image/tiff"; + case "raw": + case "arw": + case "cr2": + case "k25": + return "image/raw"; + case "svg": + case "svgz": + return "image/svg+xml"; + case "ico": + return "image/x-icon"; + case "avif": + return MimeTypes.IMAGE_AVIF; + default: + return null; + } + } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ImageUtil.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ImageUtil.java deleted file mode 100644 index ea3803bb87..0000000000 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ImageUtil.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package androidx.media3.transformer; - -import android.net.Uri; -import androidx.annotation.Nullable; -import androidx.media3.common.MimeTypes; -import androidx.media3.common.util.UnstableApi; -import com.google.common.base.Ascii; - -/** Utility methods for images. */ -@UnstableApi -public final class ImageUtil { - - private ImageUtil() {} - - /** - * Returns the {@linkplain MimeTypes MIME type} corresponding to an image {@linkplain Uri URI} - * path extension. {@code null} is returned if the extension is not an image extension. - */ - @Nullable - public static String getCommonImageMimeTypeFromExtension(Uri uri) { - @Nullable String path = uri.getPath(); - if (path == null) { - return null; - } - int extensionIndex = path.lastIndexOf('.'); - if (extensionIndex == -1 || extensionIndex == path.length() - 1) { - return null; - } - String extension = Ascii.toLowerCase(path.substring(extensionIndex + 1)); - switch (extension) { - case "bmp": - case "dib": - return MimeTypes.IMAGE_BMP; - case "heif": - return MimeTypes.IMAGE_HEIF; - case "heic": - return MimeTypes.IMAGE_HEIC; - case "jpg": - case "jpeg": - case "jpe": - case "jif": - case "jfif": - case "jfi": - return MimeTypes.IMAGE_JPEG; - case "png": - return MimeTypes.IMAGE_PNG; - case "webp": - return MimeTypes.IMAGE_WEBP; - case "gif": - return "image/gif"; - case "tiff": - case "tif": - return "image/tiff"; - case "raw": - case "arw": - case "cr2": - case "k25": - return "image/raw"; - case "svg": - case "svgz": - return "image/svg+xml"; - case "ico": - return "image/x-icon"; - case "avif": - return MimeTypes.IMAGE_AVIF; - default: - return null; - } - } -}