mirror of
https://github.com/samsonjs/media.git
synced 2026-03-30 10:15:48 +00:00
Add ImageDecoder.Factory
PiperOrigin-RevId: 557498045
This commit is contained in:
parent
2156f94480
commit
a801f8d3f5
3 changed files with 161 additions and 1 deletions
|
|
@ -25,9 +25,14 @@ import android.graphics.BitmapFactory;
|
|||
import android.graphics.Matrix;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.decoder.SimpleDecoder;
|
||||
import androidx.media3.exoplayer.RendererCapabilities;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
|
@ -44,6 +49,36 @@ public class DefaultImageDecoder
|
|||
extends SimpleDecoder<DecoderInputBuffer, ImageOutputBuffer, ImageDecoderException>
|
||||
implements ImageDecoder {
|
||||
|
||||
/** A factory for {@link DefaultImageDecoder} instances. */
|
||||
public static final class Factory implements ImageDecoder.Factory {
|
||||
|
||||
private static final ImmutableSet<String> SUPPORTED_IMAGE_TYPES =
|
||||
ImmutableSet.of(
|
||||
MimeTypes.IMAGE_PNG,
|
||||
MimeTypes.IMAGE_JPEG,
|
||||
MimeTypes.IMAGE_BMP,
|
||||
MimeTypes.IMAGE_HEIF,
|
||||
MimeTypes.IMAGE_WEBP);
|
||||
|
||||
@Override
|
||||
public @RendererCapabilities.Capabilities int supportsFormat(Format format) {
|
||||
if (!MimeTypes.isImage(format.containerMimeType)) {
|
||||
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
|
||||
}
|
||||
if (format.tileCountHorizontal != 1 || format.tileCountVertical != 1) {
|
||||
return RendererCapabilities.create(C.FORMAT_EXCEEDS_CAPABILITIES);
|
||||
}
|
||||
return SUPPORTED_IMAGE_TYPES.contains(format.containerMimeType)
|
||||
? RendererCapabilities.create(C.FORMAT_HANDLED)
|
||||
: RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultImageDecoder createImageDecoder() {
|
||||
return new DefaultImageDecoder();
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates an instance. */
|
||||
public DefaultImageDecoder() {
|
||||
super(new DecoderInputBuffer[1], new ImageOutputBuffer[1]);
|
||||
|
|
@ -98,7 +133,7 @@ public class DefaultImageDecoder
|
|||
* @return The decoded {@link Bitmap}.
|
||||
* @throws ImageDecoderException If a decoding error occurs.
|
||||
*/
|
||||
protected Bitmap decode(byte[] data, int length) throws ImageDecoderException {
|
||||
/* package */ Bitmap decode(byte[] data, int length) throws ImageDecoderException {
|
||||
@Nullable Bitmap bitmap = BitmapFactory.decodeByteArray(data, /* offset= */ 0, length);
|
||||
if (bitmap == null) {
|
||||
throw new ImageDecoderException(
|
||||
|
|
|
|||
|
|
@ -17,15 +17,37 @@ package androidx.media3.exoplayer.image;
|
|||
|
||||
import android.graphics.Bitmap;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.decoder.Decoder;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.RendererCapabilities.Capabilities;
|
||||
|
||||
/** A {@link Decoder} implementation for images. */
|
||||
@UnstableApi
|
||||
public interface ImageDecoder
|
||||
extends Decoder<DecoderInputBuffer, ImageOutputBuffer, ImageDecoderException> {
|
||||
|
||||
/** A factory for image decoders. */
|
||||
interface Factory {
|
||||
|
||||
/** Default implementation of an image decoder factory. */
|
||||
ImageDecoder.Factory DEFAULT = new DefaultImageDecoder.Factory();
|
||||
|
||||
/**
|
||||
* Returns the highest {@link Capabilities} of the factory's decoders for the given {@link
|
||||
* Format}.
|
||||
*
|
||||
* @param format The {@link Format}.
|
||||
* @return The {@link Capabilities} of the decoders the factory can instantiate for this format.
|
||||
*/
|
||||
@Capabilities
|
||||
int supportsFormat(Format format);
|
||||
|
||||
/** Creates a new {@link ImageDecoder}. */
|
||||
ImageDecoder createImageDecoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues an {@link DecoderInputBuffer} to the decoder.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright 2023 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.exoplayer.image;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.exoplayer.RendererCapabilities;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/** Unit tests for {@link DefaultImageDecoder.Factory}. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DefaultImageDecoderFactoryTest {
|
||||
|
||||
private final DefaultImageDecoder.Factory imageDecoderFactory = new DefaultImageDecoder.Factory();
|
||||
|
||||
@Test
|
||||
public void supportsFormat_validFormat_returnsFormatSupported() throws Exception {
|
||||
Format.Builder format =
|
||||
new Format.Builder()
|
||||
.setContainerMimeType(MimeTypes.IMAGE_JPEG)
|
||||
.setTileCountVertical(1)
|
||||
.setTileCountHorizontal(1);
|
||||
|
||||
assertThat(imageDecoderFactory.supportsFormat(format.build()))
|
||||
.isEqualTo(RendererCapabilities.create(C.FORMAT_HANDLED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsFormat_unsetTileCounts_returnsExceedsCapabilities() throws Exception {
|
||||
Format.Builder format = new Format.Builder().setContainerMimeType(MimeTypes.IMAGE_JPEG);
|
||||
|
||||
assertThat(imageDecoderFactory.supportsFormat(format.build()))
|
||||
.isEqualTo(RendererCapabilities.create(C.FORMAT_EXCEEDS_CAPABILITIES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsFormat_unsetTileCountVertical_returnsExceedsCapabilities() throws Exception {
|
||||
Format.Builder format = new Format.Builder().setContainerMimeType(MimeTypes.IMAGE_JPEG);
|
||||
|
||||
format.setTileCountVertical(1);
|
||||
|
||||
assertThat(imageDecoderFactory.supportsFormat(format.build()))
|
||||
.isEqualTo(RendererCapabilities.create(C.FORMAT_EXCEEDS_CAPABILITIES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsFormat_unsetTileCountHorizontal_returnsExceedsCapabilities()
|
||||
throws Exception {
|
||||
Format.Builder format = new Format.Builder().setContainerMimeType(MimeTypes.IMAGE_JPEG);
|
||||
|
||||
format.setTileCountHorizontal(1);
|
||||
|
||||
assertThat(imageDecoderFactory.supportsFormat(format.build()))
|
||||
.isEqualTo(RendererCapabilities.create(C.FORMAT_EXCEEDS_CAPABILITIES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsFormat_noContainerMimeType_returnsUnsupportedType() throws Exception {
|
||||
Format.Builder format = new Format.Builder().setTileCountHorizontal(1).setTileCountVertical(1);
|
||||
|
||||
assertThat(imageDecoderFactory.supportsFormat(format.build()))
|
||||
.isEqualTo(RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsFormat_nonImageMimeType_returnsUnsupportedType() throws Exception {
|
||||
Format.Builder format = new Format.Builder().setTileCountHorizontal(1).setTileCountVertical(1);
|
||||
|
||||
format.setContainerMimeType(MimeTypes.VIDEO_AV1);
|
||||
|
||||
assertThat(imageDecoderFactory.supportsFormat(format.build()))
|
||||
.isEqualTo(RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsFormat_unsupportedImageMimeType_returnsUnsupportedSubType() throws Exception {
|
||||
Format.Builder format = new Format.Builder().setTileCountHorizontal(1).setTileCountVertical(1);
|
||||
|
||||
format.setContainerMimeType("image/custom");
|
||||
|
||||
assertThat(imageDecoderFactory.supportsFormat(format.build()))
|
||||
.isEqualTo(RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue