From 1944c1397d9f46afc40b579d1630b6a65997c329 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Fri, 24 May 2024 09:33:18 +0200 Subject: [PATCH] image_reader: Add `AImageReader_newWithDataSpace()` from `api-level-34` (#474) Android 14 (U, API level 34) adds `DataSpace` support to `ImageReader` with a new constructor and a getter, and finally switches to the regular `HardwareBufferFormat` instead of the restricted `ImageFormat` enum to select the underlying buffer format. After all, an `AImage` can be turned into a `HardwareBuffer` which supports a wider range of formats. Also clean up and commonize some panics on pedantic `.try_from()` checks. --- ndk/CHANGELOG.md | 2 ++ ndk/Cargo.toml | 3 +- ndk/src/hardware_buffer.rs | 2 +- ndk/src/media/image_reader.rs | 56 +++++++++++++++++++++++++++++++---- ndk/src/surface_texture.rs | 2 +- 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/ndk/CHANGELOG.md b/ndk/CHANGELOG.md index e4dc75d9..4bc9a7e2 100644 --- a/ndk/CHANGELOG.md +++ b/ndk/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased +- image_reader: Add `ImageReader::new_with_data_space()` constructor and `ImageReader::data_space()` getter from API level 34. (#474) + # 0.9.0 (2024-04-26) - Move `MediaFormat` from `media::media_codec` to its own `media::media_format` module. (#442) diff --git a/ndk/Cargo.toml b/ndk/Cargo.toml index 553c1355..e9205327 100644 --- a/ndk/Cargo.toml +++ b/ndk/Cargo.toml @@ -14,7 +14,7 @@ rust-version = "1.66" [features] default = ["rwh_06"] -all = ["audio", "bitmap", "media", "nativewindow", "sync", "api-level-33", "rwh_04", "rwh_05", "rwh_06"] +all = ["audio", "bitmap", "media", "nativewindow", "sync", "api-level-34", "rwh_04", "rwh_05", "rwh_06"] audio = ["ffi/audio", "api-level-26"] bitmap = ["ffi/bitmap"] @@ -33,6 +33,7 @@ api-level-30 = ["api-level-29"] api-level-31 = ["api-level-30"] api-level-32 = ["api-level-31"] api-level-33 = ["api-level-32"] +api-level-34 = ["api-level-33"] test = ["ffi/test", "jni", "all"] diff --git a/ndk/src/hardware_buffer.rs b/ndk/src/hardware_buffer.rs index 252b8bb1..e5d4e3e3 100644 --- a/ndk/src/hardware_buffer.rs +++ b/ndk/src/hardware_buffer.rs @@ -593,7 +593,7 @@ impl HardwareBufferDesc { layers: self.layers, format: i32::from(self.format) .try_into() - .expect("i32->u32 overflow in HardwareBufferDesc::into_native()"), + .expect("Unexpected sign bit in `format`"), usage: self.usage.bits(), stride: self.stride, rfu0: 0, diff --git a/ndk/src/media/image_reader.rs b/ndk/src/media/image_reader.rs index 62488faf..2e684cd8 100644 --- a/ndk/src/media/image_reader.rs +++ b/ndk/src/media/image_reader.rs @@ -4,22 +4,25 @@ //! [`AImage`]: https://developer.android.com/ndk/reference/group/media#aimage #![cfg(feature = "api-level-24")] -use crate::media_error::{construct, construct_never_null, MediaError, Result}; -use crate::native_window::NativeWindow; -use crate::utils::abort_on_panic; -use num_enum::{FromPrimitive, IntoPrimitive}; -use std::{ffi::c_void, fmt, mem::MaybeUninit, ptr::NonNull}; - #[cfg(feature = "api-level-26")] use std::os::fd::{FromRawFd, IntoRawFd, OwnedFd}; +use std::{ffi::c_void, fmt, mem::MaybeUninit, ptr::NonNull}; + +use num_enum::{FromPrimitive, IntoPrimitive}; #[cfg(feature = "api-level-26")] use crate::hardware_buffer::{HardwareBuffer, HardwareBufferUsage}; +use crate::media_error::{construct, construct_never_null, MediaError, Result}; +use crate::native_window::NativeWindow; +use crate::utils::abort_on_panic; +#[cfg(feature = "api-level-34")] +use crate::{data_space::DataSpace, hardware_buffer_format::HardwareBufferFormat}; #[repr(i32)] #[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)] #[allow(non_camel_case_types)] #[non_exhaustive] +#[doc(alias = "AIMAGE_FORMATS")] pub enum ImageFormat { RGBA_8888 = ffi::AIMAGE_FORMATS::AIMAGE_FORMAT_RGBA_8888.0 as i32, RGBX_8888 = ffi::AIMAGE_FORMATS::AIMAGE_FORMAT_RGBX_8888.0 as i32, @@ -44,9 +47,13 @@ pub enum ImageFormat { __Unknown(i32), } +#[doc(alias = "AImageReader_ImageCallback")] +#[doc(alias = "AImageReader_ImageListener")] pub type ImageListener = Box; #[cfg(feature = "api-level-26")] +#[doc(alias = "AImageReader_BufferRemovedCallback")] +#[doc(alias = "AImageReader_BufferRemovedListener")] pub type BufferRemovedListener = Box; /// Result returned by: @@ -108,6 +115,7 @@ impl AcquireResult { /// A native [`AImageReader *`] /// /// [`AImageReader *`]: https://developer.android.com/ndk/reference/group/media#aimagereader +#[doc(alias = "AImageReader")] pub struct ImageReader { inner: NonNull, image_cb: Option>, @@ -144,6 +152,7 @@ impl ImageReader { self.inner.as_ptr() } + #[doc(alias = "AImageReader_new")] pub fn new(width: i32, height: i32, format: ImageFormat, max_images: i32) -> Result { let inner = construct_never_null(|res| unsafe { ffi::AImageReader_new(width, height, format.into(), max_images, res) @@ -153,6 +162,7 @@ impl ImageReader { } #[cfg(feature = "api-level-26")] + #[doc(alias = "AImageReader_newWithUsage")] pub fn new_with_usage( width: i32, height: i32, @@ -174,6 +184,33 @@ impl ImageReader { Ok(Self::from_ptr(inner)) } + #[cfg(feature = "api-level-34")] + #[doc(alias = "AImageReader_newWithDataSpace")] + pub fn new_with_data_space( + width: i32, + height: i32, + usage: HardwareBufferUsage, + max_images: i32, + format: HardwareBufferFormat, + data_space: DataSpace, + ) -> Result { + let inner = construct_never_null(|res| unsafe { + ffi::AImageReader_newWithDataSpace( + width, + height, + usage.bits(), + max_images, + i32::from(format) + .try_into() + .expect("Unexpected sign bit in `format`"), + data_space.into(), + res, + ) + })?; + + Ok(Self::from_ptr(inner)) + } + #[doc(alias = "AImageReader_setImageListener")] pub fn set_image_listener(&mut self, listener: ImageListener) -> Result<()> { let mut boxed = Box::new(listener); @@ -444,6 +481,13 @@ impl Image { unsafe { ffi::AImage_deleteAsync(self.as_ptr(), release_fence_fd.into_raw_fd()) }; std::mem::forget(self); } + + #[cfg(feature = "api-level-34")] + #[doc(alias = "AImage_getDataSpace")] + pub fn data_space(&self) -> Result { + construct(|res| unsafe { ffi::AImage_getDataSpace(self.as_ptr(), res) }) + .map(DataSpace::from) + } } impl Drop for Image { diff --git a/ndk/src/surface_texture.rs b/ndk/src/surface_texture.rs index d38ffd7a..943b949e 100644 --- a/ndk/src/surface_texture.rs +++ b/ndk/src/surface_texture.rs @@ -143,7 +143,7 @@ impl SurfaceTexture { Duration::from_nanos( unsafe { ffi::ASurfaceTexture_getTimestamp(self.ptr.as_ptr()) } .try_into() - .unwrap(), + .expect("Timestamp cannot be negative"), ) }