diff --git a/libraries/effect/src/main/java/androidx/media3/effect/BitmapToHardwareBufferProcessor.java b/libraries/effect/src/main/java/androidx/media3/effect/BitmapToHardwareBufferProcessor.java index 9c150ad01e9..3a03f0a0e26 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/BitmapToHardwareBufferProcessor.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/BitmapToHardwareBufferProcessor.java @@ -116,7 +116,9 @@ public HardwareBufferFrame process(HardwareBufferFrame inputFrame) { if (currentFrame == null) { HardwareBuffer buffer = null; try { - if (SDK_INT >= 31) { + if (nextBitmap.getConfig() == Config.RGBA_1010102) { + buffer = copyCpuBitmapToHardwareBuffer(nextBitmap, hardwareBufferJniWrapper); + } else if (SDK_INT >= 31) { if (nextBitmap.getConfig() == Config.HARDWARE) { // Input is HARDWARE and API >= 31: Direct access to HardwareBuffer is possible. buffer = nextBitmap.getHardwareBuffer(); @@ -199,16 +201,19 @@ public void close() { *

The created buffer will have {@linkplain HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE GPU read}, * {@linkplain HardwareBuffer#USAGE_GPU_COLOR_OUTPUT GPU write}, {@linkplain * HardwareBuffer#USAGE_CPU_READ_OFTEN CPU read} and {@linkplain - * HardwareBuffer#USAGE_CPU_WRITE_OFTEN CPU write} usage flags set, and pixelFormat of {@link - * HardwareBuffer#RGBA_8888}. + * HardwareBuffer#USAGE_CPU_WRITE_OFTEN CPU write} usage flags set. */ private static HardwareBuffer copyCpuBitmapToHardwareBuffer( Bitmap bitmap, HardwareBufferJniWrapper hardwareBufferJniWrapper) { + int pixelFormat = + bitmap.getConfig() == Config.RGBA_1010102 + ? HardwareBuffer.RGBA_1010102 + : HardwareBuffer.RGBA_8888; HardwareBuffer buffer = HardwareBuffer.create( bitmap.getWidth(), bitmap.getHeight(), - /* pixelFormat= */ HardwareBuffer.RGBA_8888, + pixelFormat, /* layers= */ 1, /* usageFlags= */ HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/HardwareBufferFrameReader.java b/libraries/transformer/src/main/java/androidx/media3/transformer/HardwareBufferFrameReader.java index 76fab66ea92..a7bd3c3f15c 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/HardwareBufferFrameReader.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/HardwareBufferFrameReader.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkState; import android.graphics.Bitmap; +import android.graphics.ColorSpace; import android.hardware.HardwareBuffer; import android.os.Handler; import android.os.Looper; @@ -228,7 +229,7 @@ void outputBitmap( .setSampleMimeType(MimeTypes.IMAGE_RAW) .setWidth(bitmap.getWidth()) .setHeight(bitmap.getHeight()) - .setColorInfo(ColorInfo.SRGB_BT709_FULL) + .setColorInfo(resolveColorInfoFromBitmap(bitmap)) .setFrameRate(/* frameRate= */ DEFAULT_FRAME_RATE) .build(); synchronized (this) { @@ -505,6 +506,29 @@ private void maybeWakeupVideoRenderer() { } } + private static ColorInfo resolveColorInfoFromBitmap(Bitmap bitmap) { + if (SDK_INT >= 34) { + ColorSpace colorSpace = bitmap.getColorSpace(); + if (colorSpace != null) { + int id = colorSpace.getId(); + if (id == ColorSpace.get(ColorSpace.Named.BT2020_HLG).getId()) { + return new ColorInfo.Builder() + .setColorSpace(C.COLOR_SPACE_BT2020) + .setColorRange(C.COLOR_RANGE_FULL) + .setColorTransfer(C.COLOR_TRANSFER_HLG) + .build(); + } else if (id == ColorSpace.get(ColorSpace.Named.BT2020_PQ).getId()) { + return new ColorInfo.Builder() + .setColorSpace(C.COLOR_SPACE_BT2020) + .setColorRange(C.COLOR_RANGE_FULL) + .setColorTransfer(C.COLOR_TRANSFER_ST2084) + .build(); + } + } + } + return ColorInfo.SRGB_BT709_FULL; + } + /** * A {@link Executor} which executes commands on a {@link Handler} and propagates {@linkplain * RuntimeException errors} to the {@link Listener}.