Skip to content

Android: Add hardware-backed Bitmap decode API#3109

Open
thebehera wants to merge 2 commits intoAOMediaCodec:mainfrom
thebehera:android/hardware-bitmap
Open

Android: Add hardware-backed Bitmap decode API#3109
thebehera wants to merge 2 commits intoAOMediaCodec:mainfrom
thebehera:android/hardware-bitmap

Conversation

@thebehera
Copy link
Copy Markdown

@thebehera thebehera commented Mar 19, 2026

Adds API to decode AVIF images directly into hardware-backed Bitmaps
(Config.HARDWARE), bypassing the software Bitmap intermediary.

New API

Still images

AvifDecoder.isHighBitDepthDisplaySupported(Display)
AvifDecoder.decodeHardwareBitmap(ByteBuffer, int)
AvifDecoder.decodeHardwareBitmap(ByteBuffer, int, int)
AvifDecoder.decodeHardwareBitmap(ByteBuffer, int, int, boolean allowHdr)

Animated images (instance methods)

decoder.createHardwareBuffer(boolean allowHdr)
decoder.nextFrameHardwareBitmap(boolean allowHdr)
decoder.nextFrameHardwareBitmap(boolean allowHdr, @nullable HardwareBuffer dest)
decoder.nthFrameHardwareBitmap(int n, boolean allowHdr)
decoder.nthFrameHardwareBitmap(int n, boolean allowHdr, @nullable HardwareBuffer dest)

Passing null for dest allocates a new HardwareBuffer on each call.
Passing a pre-allocated buffer (from createHardwareBuffer) enables zero-copy frame reuse: decode all frames into the same buffer, and a single Bitmap wrapping it reflects new content without re-allocation.

Implementation

  • Fast path: allocates R16G16B16A16_FLOAT (FP16, >8-bit + allowHdr) or
    R8G8B8A8_UNORM, locks the buffer, decodes YUV→RGB directly into it.
  • Slow fallback: if FP16 is unsupported, falls back to R8G8B8A8_UNORM.
  • Color space derived from CICP metadata: BT2020_PQ (API 33+), BT2020_HLG (API 34+), SRGB for other FP16, null for SDR.
  • Returns null on API < 26 or decode failure.
  • Uses ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK (NDK 25) for API 21+ compatibility.

@thebehera thebehera force-pushed the android/hardware-bitmap branch from a41d93b to 1107f45 Compare March 19, 2026 03:08
Adds new methods to AvifDecoder that decode AVIF images directly into
AHardwareBuffer and return hardware-backed Bitmaps (Bitmap.Config.HARDWARE).
Hardware Bitmaps are GPU-resident, require no CPU→GPU upload, and are
directly compatible with Canvas, ImageView, and Drawable.

New API (requires API 26):
  AvifDecoder.decodeHardwareBitmap(ByteBuffer, int, int[, boolean])
  AvifDecoder.nextFrameHardwareBitmap([boolean])
  AvifDecoder.nthFrameHardwareBitmap(int[, boolean])
  AvifDecoder.isHighBitDepthDisplaySupported(Display)

The allowHdr parameter controls format selection: when true and the
image has depth > 8, an R16G16B16A16_FLOAT AHardwareBuffer is tried
first to preserve HDR precision (PQ/HLG color spaces tagged accordingly).
Falls back to R8G8B8A8_UNORM if FP16 is unsupported or allowHdr is false.

avifImageYUVToRGB decodes directly into the locked AHardwareBuffer memory
with no intermediate copy. ApplyCrop is introduced as a shared helper
used by both the software Bitmap and hardware Bitmap decode paths.

Uses __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ (NDK 25) so AHardwareBuffer
symbols are weak-linked and the library remains loadable on API < 26.
@thebehera thebehera force-pushed the android/hardware-bitmap branch from 1107f45 to 0d21c76 Compare March 19, 2026 03:10
After nthFrameHardwareBitmap(0), the decoder is positioned at frame 0,
so nextFrameHardwareBitmap advances to frame 1 on the first call.
Looping frameCount times overshoots by one, hitting
AVIF_RESULT_NO_IMAGES_REMAINING on the last iteration.

Switch the buffer-reuse loop to nthFrameHardwareBitmap(i, ...) which
iterates frames 0 through frameCount-1 cleanly, and add a separate
assertion to verify nextFrameHardwareBitmap with a dest buffer.
@thebehera thebehera force-pushed the android/hardware-bitmap branch from 8557c18 to e60e863 Compare March 19, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant