Skip to content

Commit

Permalink
ndk/media: Move MediaFormat to its own module (#442)
Browse files Browse the repository at this point in the history
This type is used outside of `media_codec`, for example in the
`media_extractor` bindings.
  • Loading branch information
MarijnS95 committed Oct 24, 2023
1 parent 407a822 commit 6a98868
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 206 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

- Move `MediaFormat` from `media::media_codec` to its own `media::media_format` module. (#442)

# 0.8.0 (2023-10-15)

- event: Add `tool_type` getter for `Pointer`. (#323)
Expand Down
215 changes: 9 additions & 206 deletions ndk/src/media/media_codec.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
//! Bindings for [`AMediaFormat`] and [`AMediaCodec`]
//! Bindings for [`AMediaCodec`]
//!
//! [`AMediaFormat`]: https://developer.android.com/ndk/reference/group/media#amediaformat
//! [`AMediaCodec`]: https://developer.android.com/ndk/reference/group/media#amediacodec

#[deprecated = "MediaFormat should be referenced directly from the media_format module"]
pub use super::media_format::MediaFormat;
use crate::media_error::{MediaError, Result};
use crate::native_window::NativeWindow;
use crate::utils::abort_on_panic;
use std::{
ffi::{c_char, c_void, CStr, CString},
fmt::Display,
fmt,
mem::MaybeUninit,
pin::Pin,
ptr::{self, NonNull},
Expand All @@ -22,204 +23,6 @@ pub enum MediaCodecDirection {
Encoder,
}

/// A native [`AMediaFormat *`]
///
/// [`AMediaFormat *`]: https://developer.android.com/ndk/reference/group/media#amediaformat
#[derive(Debug)]
pub struct MediaFormat {
inner: NonNull<ffi::AMediaFormat>,
}

impl Display for MediaFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let c_str = unsafe { CStr::from_ptr(ffi::AMediaFormat_toString(self.as_ptr())) };
f.write_str(c_str.to_str().unwrap())
}
}

impl Default for MediaFormat {
fn default() -> Self {
Self::new()
}
}

impl MediaFormat {
/// Assumes ownership of `ptr`
///
/// # Safety
/// `ptr` must be a valid pointer to an Android [`ffi::AMediaFormat`].
pub unsafe fn from_ptr(ptr: NonNull<ffi::AMediaFormat>) -> Self {
Self { inner: ptr }
}

fn as_ptr(&self) -> *mut ffi::AMediaFormat {
self.inner.as_ptr()
}

pub fn new() -> Self {
Self {
inner: NonNull::new(unsafe { ffi::AMediaFormat_new() }).unwrap(),
}
}

pub fn i32(&self, key: &str) -> Option<i32> {
let name = CString::new(key).unwrap();
let mut out = 0;
if unsafe { ffi::AMediaFormat_getInt32(self.as_ptr(), name.as_ptr(), &mut out) } {
Some(out)
} else {
None
}
}

pub fn i64(&self, key: &str) -> Option<i64> {
let name = CString::new(key).unwrap();
let mut out = 0;
if unsafe { ffi::AMediaFormat_getInt64(self.as_ptr(), name.as_ptr(), &mut out) } {
Some(out)
} else {
None
}
}

pub fn f32(&self, key: &str) -> Option<f32> {
let name = CString::new(key).unwrap();
let mut out = 0.0;
if unsafe { ffi::AMediaFormat_getFloat(self.as_ptr(), name.as_ptr(), &mut out) } {
Some(out)
} else {
None
}
}

pub fn usize(&self, key: &str) -> Option<usize> {
let name = CString::new(key).unwrap();
let mut out = 0;
if unsafe { ffi::AMediaFormat_getSize(self.as_ptr(), name.as_ptr(), &mut out) } {
Some(out)
} else {
None
}
}

pub fn buffer(&self, key: &str) -> Option<&[u8]> {
let name = CString::new(key).unwrap();
let mut out_buffer = ptr::null_mut();
let mut out_size = 0;
unsafe {
ffi::AMediaFormat_getBuffer(
self.as_ptr(),
name.as_ptr(),
&mut out_buffer,
&mut out_size,
)
}
.then(|| unsafe { slice::from_raw_parts(out_buffer.cast(), out_size) })
}

pub fn str(&self, key: &str) -> Option<&str> {
let name = CString::new(key).unwrap();
let mut out = ptr::null();
unsafe { ffi::AMediaFormat_getString(self.as_ptr(), name.as_ptr(), &mut out) }
.then(|| unsafe { CStr::from_ptr(out) }.to_str().unwrap())
}

pub fn set_i32(&self, key: &str, value: i32) {
let name = CString::new(key).unwrap();
unsafe { ffi::AMediaFormat_setInt32(self.as_ptr(), name.as_ptr(), value) };
}

pub fn set_i64(&self, key: &str, value: i64) {
let name = CString::new(key).unwrap();
unsafe { ffi::AMediaFormat_setInt64(self.as_ptr(), name.as_ptr(), value) };
}

pub fn set_f32(&self, key: &str, value: f32) {
let name = CString::new(key).unwrap();
unsafe { ffi::AMediaFormat_setFloat(self.as_ptr(), name.as_ptr(), value) };
}

pub fn set_str(&self, key: &str, value: &str) {
let name = CString::new(key).unwrap();
let c_string = CString::new(value).unwrap();
unsafe { ffi::AMediaFormat_setString(self.as_ptr(), name.as_ptr(), c_string.as_ptr()) };
}

pub fn set_buffer(&self, key: &str, value: &[u8]) {
let name = CString::new(key).unwrap();
unsafe {
ffi::AMediaFormat_setBuffer(
self.as_ptr(),
name.as_ptr(),
value.as_ptr().cast(),
value.len(),
)
};
}

#[cfg(feature = "api-level-28")]
pub fn f64(&self, key: &str) -> Option<f64> {
let name = CString::new(key).unwrap();
let mut out = 0.0;
if unsafe { ffi::AMediaFormat_getDouble(self.as_ptr(), name.as_ptr(), &mut out) } {
Some(out)
} else {
None
}
}

/// Returns (left, top, right, bottom)
#[cfg(feature = "api-level-28")]
pub fn rect(&self, key: &str) -> Option<(i32, i32, i32, i32)> {
let name = CString::new(key).unwrap();
let mut left = 0;
let mut top = 0;
let mut right = 0;
let mut bottom = 0;
if unsafe {
ffi::AMediaFormat_getRect(
self.as_ptr(),
name.as_ptr(),
&mut left,
&mut top,
&mut right,
&mut bottom,
)
} {
Some((left, top, right, bottom))
} else {
None
}
}

#[cfg(feature = "api-level-28")]
pub fn set_f64(&self, key: &str, value: f64) {
let name = CString::new(key).unwrap();
unsafe { ffi::AMediaFormat_setDouble(self.as_ptr(), name.as_ptr(), value) };
}

#[cfg(feature = "api-level-28")]
pub fn set_rect(&self, key: &str, left: i32, top: i32, right: i32, bottom: i32) {
let name = CString::new(key).unwrap();
unsafe {
ffi::AMediaFormat_setRect(self.as_ptr(), name.as_ptr(), left, top, right, bottom)
};
}

#[cfg(feature = "api-level-28")]
pub fn set_usize(&self, key: &str, value: usize) {
let name = CString::new(key).unwrap();
unsafe { ffi::AMediaFormat_setSize(self.as_ptr(), name.as_ptr(), value) };
}
}

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

/// A native [`AMediaCodec *`]
///
/// [`AMediaCodec *`]: https://developer.android.com/ndk/reference/group/media#amediacodec
Expand Down Expand Up @@ -256,8 +59,8 @@ pub struct AsyncNotifyCallback {
pub on_error: Option<ErrorCallback>,
}

impl std::fmt::Debug for AsyncNotifyCallback {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Debug for AsyncNotifyCallback {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AsyncNotifyCallback")
.field(
"on_input_available",
Expand Down Expand Up @@ -600,13 +403,13 @@ impl MediaCodec {
pub fn input_format(&self) -> MediaFormat {
let inner = NonNull::new(unsafe { ffi::AMediaCodec_getInputFormat(self.as_ptr()) })
.expect("AMediaCodec_getInputFormat returned NULL");
MediaFormat { inner }
unsafe { MediaFormat::from_ptr(inner) }
}

pub fn output_format(&self) -> MediaFormat {
let inner = NonNull::new(unsafe { ffi::AMediaCodec_getOutputFormat(self.as_ptr()) })
.expect("AMediaCodec_getOutputFormat returned NULL");
MediaFormat { inner }
unsafe { MediaFormat::from_ptr(inner) }
}

#[cfg(feature = "api-level-28")]
Expand Down Expand Up @@ -774,7 +577,7 @@ impl OutputBuffer<'_> {
ffi::AMediaCodec_getBufferFormat(self.codec.as_ptr(), self.index)
})
.expect("AMediaCodec_getBufferFormat returned NULL");
MediaFormat { inner }
unsafe { MediaFormat::from_ptr(inner) }
}

pub fn info(&self) -> &BufferInfo {
Expand Down
Loading

0 comments on commit 6a98868

Please sign in to comment.