Skip to content

Commit

Permalink
image_reader: Add api-level-34 AImageReader_newWithDataSpace()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
MarijnS95 committed May 19, 2024
1 parent f964154 commit 79cc7d1
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 9 deletions.
2 changes: 2 additions & 0 deletions ndk/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
3 changes: 2 additions & 1 deletion ndk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand All @@ -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"]

Expand Down
2 changes: 1 addition & 1 deletion ndk/src/hardware_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
56 changes: 50 additions & 6 deletions ndk/src/media/image_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -44,9 +47,13 @@ pub enum ImageFormat {
__Unknown(i32),
}

#[doc(alias = "AImageReader_ImageCallback")]
#[doc(alias = "AImageReader_ImageListener")]
pub type ImageListener = Box<dyn FnMut(&ImageReader) + Send>;

#[cfg(feature = "api-level-26")]
#[doc(alias = "AImageReader_BufferRemovedCallback")]
#[doc(alias = "AImageReader_BufferRemovedListener")]
pub type BufferRemovedListener = Box<dyn FnMut(&ImageReader, &HardwareBuffer) + Send>;

/// Result returned by:
Expand Down Expand Up @@ -108,6 +115,7 @@ impl AcquireResult<Image> {
/// A native [`AImageReader *`]
///
/// [`AImageReader *`]: https://developer.android.com/ndk/reference/group/media#aimagereader
#[doc(alias = "AImageReader")]
pub struct ImageReader {
inner: NonNull<ffi::AImageReader>,
image_cb: Option<Box<ImageListener>>,
Expand Down Expand Up @@ -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<Self> {
let inner = construct_never_null(|res| unsafe {
ffi::AImageReader_new(width, height, format.into(), max_images, res)
Expand All @@ -153,6 +162,7 @@ impl ImageReader {
}

#[cfg(feature = "api-level-26")]
#[doc(alias = "AImageReader_newWithUsage")]
pub fn new_with_usage(
width: i32,
height: i32,
Expand All @@ -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<Self> {
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);
Expand Down Expand Up @@ -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<DataSpace> {
construct(|res| unsafe { ffi::AImage_getDataSpace(self.as_ptr(), res) })
.map(DataSpace::from)
}
}

impl Drop for Image {
Expand Down
2 changes: 1 addition & 1 deletion ndk/src/surface_texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
)
}

Expand Down

0 comments on commit 79cc7d1

Please sign in to comment.