Skip to content

Commit

Permalink
ndk: Rework media error types
Browse files Browse the repository at this point in the history
- Clean up the names: we're already in the `ndk` crate so no need to
  repeat that in the type name;
- Make the types available outside the `media` module, so that they can
  be used in `AMidi` bindings which are not located inside
  `libmediandk.so` (but `libamidi.so`);
- Add documentation comments.
  • Loading branch information
MarijnS95 committed Jun 16, 2023
1 parent 4da2e5b commit 95220e7
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 65 deletions.
1 change: 1 addition & 0 deletions ndk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- **Breaking:** Upgrade to [`ndk-sys 0.5.0`](../ndk-sys/CHANGELOG.md#050-TODO). (#370)
- **Breaking:** Upgrade `bitflags` crate from `1` to `2`. (#394)
- **Breaking:** Upgrade `num_enum` crate from `0.5.1` to `0.6`. (#398)
- **Breaking:** Renamed and moved "`media`" error types and helpers to the always-available `media_error` module. (#399)

# 0.7.0 (2022-07-24)

Expand Down
1 change: 1 addition & 0 deletions ndk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod hardware_buffer_format;
pub mod input_queue;
pub mod looper;
pub mod media;
pub mod media_error;
pub mod native_activity;
pub mod native_window;
pub mod surface_texture;
Expand Down
15 changes: 6 additions & 9 deletions ndk/src/media/image_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
//! [`AImage`]: https://developer.android.com/ndk/reference/group/media#aimage
#![cfg(feature = "api-level-24")]

use super::NdkMediaError;
use super::{construct, construct_never_null, error::MediaErrorResult, Result};
use crate::media_error::{construct, construct_never_null, MediaError, MediaStatus, Result};
use crate::native_window::NativeWindow;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use std::{
Expand Down Expand Up @@ -140,7 +139,7 @@ impl ImageReader {
onImageAvailable: Some(on_image_available),
};
let status = unsafe { ffi::AImageReader_setImageListener(self.as_ptr(), &mut listener) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

#[cfg(feature = "api-level-26")]
Expand Down Expand Up @@ -168,7 +167,7 @@ impl ImageReader {
};
let status =
unsafe { ffi::AImageReader_setBufferRemovedListener(self.as_ptr(), &mut listener) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

pub fn get_window(&self) -> Result<NativeWindow> {
Expand Down Expand Up @@ -202,9 +201,7 @@ impl ImageReader {

match res {
Ok(inner) => Ok(Some(Image { inner })),
Err(NdkMediaError::ErrorResult(MediaErrorResult::ImgreaderNoBufferAvailable)) => {
Ok(None)
}
Err(MediaError::MediaStatus(MediaStatus::ImgreaderNoBufferAvailable)) => Ok(None),
Err(e) => Err(e),
}
}
Expand Down Expand Up @@ -232,7 +229,7 @@ impl ImageReader {
ffi::AImageReader_acquireLatestImage(self.as_ptr(), res)
});

if let Err(NdkMediaError::ErrorResult(MediaErrorResult::ImgreaderNoBufferAvailable)) = res {
if let Err(MediaError::MediaStatus(MediaStatus::ImgreaderNoBufferAvailable)) = res {
return Ok(None);
}

Expand Down Expand Up @@ -291,7 +288,7 @@ impl Image {
)
};

NdkMediaError::from_status(status).map(|()| unsafe {
MediaError::from_status(status).map(|()| unsafe {
std::slice::from_raw_parts(result_ptr.assume_init(), result_len.assume_init() as _)
})
}
Expand Down
38 changes: 19 additions & 19 deletions ndk/src/media/media_codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! [`AMediaFormat`]: https://developer.android.com/ndk/reference/group/media#amediaformat
//! [`AMediaCodec`]: https://developer.android.com/ndk/reference/group/media#amediacodec

use super::{NdkMediaError, Result};
use crate::media_error::{MediaError, Result};
use crate::native_window::NativeWindow;
use std::{
convert::TryInto,
Expand Down Expand Up @@ -206,7 +206,7 @@ impl MediaFormat {
impl Drop for MediaFormat {
fn drop(&mut self) {
let status = unsafe { ffi::AMediaFormat_delete(self.as_ptr()) };
NdkMediaError::from_status(status).unwrap();
MediaError::from_status(status).unwrap();
}
}

Expand Down Expand Up @@ -267,12 +267,12 @@ impl MediaCodec {
},
)
};
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

#[cfg(feature = "api-level-26")]
pub fn create_input_surface(&self) -> Result<NativeWindow> {
use super::construct_never_null;
use crate::media_error::construct_never_null;
unsafe {
let ptr = construct_never_null(|res| {
ffi::AMediaCodec_createInputSurface(self.as_ptr(), res)
Expand All @@ -283,7 +283,7 @@ impl MediaCodec {

#[cfg(feature = "api-level-26")]
pub fn create_persistent_input_surface() -> Result<NativeWindow> {
use super::construct_never_null;
use crate::media_error::construct_never_null;
unsafe {
let ptr =
construct_never_null(|res| ffi::AMediaCodec_createPersistentInputSurface(res))?;
Expand Down Expand Up @@ -311,7 +311,7 @@ impl MediaCodec {
index: result as usize,
}))
} else {
NdkMediaError::from_status(ffi::media_status_t(result as _)).map(|()| None)
MediaError::from_status(ffi::media_status_t(result as _)).map(|()| None)
}
}

Expand Down Expand Up @@ -339,13 +339,13 @@ impl MediaCodec {
info,
}))
} else {
NdkMediaError::from_status(ffi::media_status_t(result as _)).map(|()| None)
MediaError::from_status(ffi::media_status_t(result as _)).map(|()| None)
}
}

pub fn flush(&self) -> Result<()> {
let status = unsafe { ffi::AMediaCodec_flush(self.as_ptr()) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

#[cfg(feature = "api-level-28")]
Expand All @@ -363,7 +363,7 @@ impl MediaCodec {

#[cfg(feature = "api-level-28")]
pub fn name(&self) -> Result<String> {
use super::construct;
use crate::media_error::construct;
unsafe {
let name_ptr = construct(|name| ffi::AMediaCodec_getName(self.as_ptr(), name))?;
let name = CStr::from_ptr(name_ptr).to_str().unwrap().to_owned();
Expand Down Expand Up @@ -391,13 +391,13 @@ impl MediaCodec {
flags,
)
};
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

pub fn release_output_buffer(&self, buffer: OutputBuffer, render: bool) -> Result<()> {
let status =
unsafe { ffi::AMediaCodec_releaseOutputBuffer(self.as_ptr(), buffer.index, render) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

pub fn release_output_buffer_at_time(
Expand All @@ -408,49 +408,49 @@ impl MediaCodec {
let status = unsafe {
ffi::AMediaCodec_releaseOutputBufferAtTime(self.as_ptr(), buffer.index, timestamp_ns)
};
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

#[cfg(feature = "api-level-26")]
pub fn set_input_surface(&self, surface: &NativeWindow) -> Result<()> {
let status =
unsafe { ffi::AMediaCodec_setInputSurface(self.as_ptr(), surface.ptr().as_ptr()) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

pub fn set_output_surface(&self, surface: &NativeWindow) -> Result<()> {
let status =
unsafe { ffi::AMediaCodec_setOutputSurface(self.as_ptr(), surface.ptr().as_ptr()) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

#[cfg(feature = "api-level-26")]
pub fn set_parameters(&self, params: MediaFormat) -> Result<()> {
let status = unsafe { ffi::AMediaCodec_setParameters(self.as_ptr(), params.as_ptr()) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

#[cfg(feature = "api-level-26")]
pub fn set_signal_end_of_input_stream(&self) -> Result<()> {
let status = unsafe { ffi::AMediaCodec_signalEndOfInputStream(self.as_ptr()) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

pub fn start(&self) -> Result<()> {
let status = unsafe { ffi::AMediaCodec_start(self.as_ptr()) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}

pub fn stop(&self) -> Result<()> {
let status = unsafe { ffi::AMediaCodec_stop(self.as_ptr()) };
NdkMediaError::from_status(status)
MediaError::from_status(status)
}
}

impl Drop for MediaCodec {
fn drop(&mut self) {
let status = unsafe { ffi::AMediaCodec_delete(self.as_ptr()) };
NdkMediaError::from_status(status).unwrap();
MediaError::from_status(status).unwrap();
}
}

Expand Down
24 changes: 0 additions & 24 deletions ndk/src/media/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,5 @@
//! See also [the NDK docs](https://developer.android.com/ndk/reference/group/media)
#![cfg(feature = "media")]

mod error;
pub mod image_reader;
pub mod media_codec;

pub use error::NdkMediaError;
use std::{mem::MaybeUninit, ptr::NonNull};

pub type Result<T, E = NdkMediaError> = std::result::Result<T, E>;

fn construct<T>(with_ptr: impl FnOnce(*mut T) -> ffi::media_status_t) -> Result<T> {
let mut result = MaybeUninit::uninit();
let status = with_ptr(result.as_mut_ptr());
NdkMediaError::from_status(status).map(|()| unsafe { result.assume_init() })
}

fn construct_never_null<T>(
with_ptr: impl FnOnce(*mut *mut T) -> ffi::media_status_t,
) -> Result<NonNull<T>> {
let result = construct(with_ptr)?;
let non_null = if cfg!(debug_assertions) {
NonNull::new(result).expect("result should never be null")
} else {
unsafe { NonNull::new_unchecked(result) }
};
Ok(non_null)
}
54 changes: 41 additions & 13 deletions ndk/src/media/error.rs → ndk/src/media_error.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use super::Result;
use std::{mem::MaybeUninit, ptr::NonNull};

use thiserror::Error;

pub type Result<T, E = MediaError> = std::result::Result<T, E>;

/// Media Status codes for [`media_status_t`](https://developer.android.com/ndk/reference/group/media#group___media_1ga009a49041fe39f7bdc6d8b5cddbe760c)
#[repr(i32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MediaErrorResult {
pub enum MediaStatus {
CodecErrorInsufficientResource = ffi::media_status_t::AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE.0,
CodecErrorReclaimed = ffi::media_status_t::AMEDIACODEC_ERROR_RECLAIMED.0,
ErrorUnknown = ffi::media_status_t::AMEDIA_ERROR_UNKNOWN.0,
Expand Down Expand Up @@ -33,18 +37,20 @@ pub enum MediaErrorResult {
ImgreaderImageNotLocked = ffi::media_status_t::AMEDIA_IMGREADER_IMAGE_NOT_LOCKED.0,
}

/// Media Status codes in [`MediaStatus`] or raw [`ffi::media_status_t`] if unknown.
#[derive(Debug, Error)]
pub enum NdkMediaError {
#[error("error Media result ({0:?})")]
ErrorResult(MediaErrorResult),
#[error("unknown Media error result ({0:?})")]
UnknownResult(ffi::media_status_t),
pub enum MediaError {
#[error("Media Status {0:?}")]
MediaStatus(MediaStatus),
#[error("Unknown Media Status {0:?}")]
UnknownStatus(ffi::media_status_t),
}

impl NdkMediaError {
impl MediaError {
/// Returns [`Ok`] on [`ffi::media_status_t::AMEDIA_OK`], [`Err`] otherwise.
pub(crate) fn from_status(status: ffi::media_status_t) -> Result<()> {
use MediaErrorResult::*;
let result = match status {
use MediaStatus::*;
Err(Self::MediaStatus(match status {
ffi::media_status_t::AMEDIA_OK => return Ok(()),
ffi::media_status_t::AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE => {
CodecErrorInsufficientResource
Expand Down Expand Up @@ -75,8 +81,30 @@ impl NdkMediaError {
ffi::media_status_t::AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE => ImgreaderCannotLockImage,
ffi::media_status_t::AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE => ImgreaderCannotUnlockImage,
ffi::media_status_t::AMEDIA_IMGREADER_IMAGE_NOT_LOCKED => ImgreaderImageNotLocked,
_ => return Err(NdkMediaError::UnknownResult(status)),
};
Err(NdkMediaError::ErrorResult(result))
_ => return Err(MediaError::UnknownStatus(status)),
}))
}
}

/// Calls the `with_ptr` construction function with a pointer to uninitialized stack memory,
/// expecting `with_ptr` to initialize it or otherwise return an error code.
pub(crate) fn construct<T>(with_ptr: impl FnOnce(*mut T) -> ffi::media_status_t) -> Result<T> {
let mut result = MaybeUninit::uninit();
let status = with_ptr(result.as_mut_ptr());
MediaError::from_status(status).map(|()| unsafe { result.assume_init() })
}

/// Calls the `with_ptr` construction function with a pointer to a pointer, and expects `with_ptr`
/// to initialize the second pointer to a valid address. That address is returned in the form of a
/// [`NonNull`] object.
pub(crate) fn construct_never_null<T>(
with_ptr: impl FnOnce(*mut *mut T) -> ffi::media_status_t,
) -> Result<NonNull<T>> {
let result = construct(with_ptr)?;
let non_null = if cfg!(debug_assertions) {
NonNull::new(result).expect("result should never be null")
} else {
unsafe { NonNull::new_unchecked(result) }
};
Ok(non_null)
}

0 comments on commit 95220e7

Please sign in to comment.