Skip to content

Commit 58f058e

Browse files
committed
ndk/media: Add bindings for AMediaCodecCryptoInfo
1 parent 2d269e1 commit 58f058e

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
//! Bindings for [`AMediaCodecCryptoInfo`]
2+
//!
3+
//! [`AMediaCodecCryptoInfo`]: https://developer.android.com/ndk/reference/group/media#amediacodeccryptoinfo
4+
5+
use std::{mem::MaybeUninit, ptr::NonNull};
6+
7+
use crate::media_error::{MediaError, Result};
8+
9+
/// A native [`AMediaCodecCryptoInfo *`]
10+
///
11+
/// [`AMediaCodecCryptoInfo *`]: https://developer.android.com/ndk/reference/group/media#amediacodeccryptoinfo
12+
#[derive(Debug)]
13+
#[doc(alias = "AMediaCodecCryptoInfo")]
14+
pub struct MediaCodecCryptoInfo {
15+
inner: NonNull<ffi::AMediaCodecCryptoInfo>,
16+
}
17+
18+
impl MediaCodecCryptoInfo {
19+
/// Create a [`MediaCodecCryptoInfo`] from scratch. Use this if you need to use custom crypto
20+
/// info, rather than one obtained from [`super::media_extractor::MediaExtractor`].
21+
///
22+
/// [`MediaCodecCryptoInfo`] describes the structure of an (at least partially) encrypted input
23+
/// sample.
24+
///
25+
/// A buffer's data is considered to be partitioned into "subsamples", each subsample starts
26+
/// with a (potentially empty) run of plain, unencrypted bytes followed by a (also potentially
27+
/// empty) run of encrypted bytes.
28+
///
29+
/// `clearbytes` can be null to indicate that all data is encrypted. This information
30+
/// encapsulates per-sample metadata as outlined in ISO/IEC FDIS 23001-7:2011 "Common encryption
31+
/// in ISO base media file format files".
32+
#[doc(alias = "AMediaCodecCryptoInfo_new")]
33+
pub fn new(
34+
num_sub_samples: i32,
35+
key: &[u8; 16],
36+
iv: &[u8; 16],
37+
mode: ffi::cryptoinfo_mode_t,
38+
) -> Option<Self> {
39+
let mut clear_bytes = 0;
40+
let mut encrypted_bytes = 0;
41+
NonNull::new(unsafe {
42+
ffi::AMediaCodecCryptoInfo_new(
43+
num_sub_samples,
44+
key.as_ptr().cast_mut(),
45+
iv.as_ptr().cast_mut(),
46+
mode,
47+
// TODO: Set the value and/or store it?
48+
&mut clear_bytes,
49+
&mut encrypted_bytes,
50+
)
51+
})
52+
.map(|inner| Self { inner })
53+
}
54+
55+
/// Assumes ownership of `ptr`
56+
///
57+
/// # Safety
58+
/// `ptr` must be a valid pointer to an Android [`ffi::AMediaCodecCryptoInfo`].
59+
pub unsafe fn from_ptr(ptr: NonNull<ffi::AMediaCodecCryptoInfo>) -> Self {
60+
Self { inner: ptr }
61+
}
62+
63+
pub fn as_ptr(&self) -> *mut ffi::AMediaCodecCryptoInfo {
64+
self.inner.as_ptr()
65+
}
66+
67+
/// Set the crypto pattern on an AMediaCryptoInfo object.
68+
#[doc(alias = "AMediaCodecCryptoInfo_setPattern")]
69+
pub fn set_pattern(&self, pattern: &ffi::cryptoinfo_pattern_t) {
70+
unsafe {
71+
ffi::AMediaCodecCryptoInfo_setPattern(
72+
self.inner.as_ptr(),
73+
<*const _>::cast_mut(pattern),
74+
)
75+
}
76+
}
77+
78+
/// The number of subsamples that make up the buffer's contents.
79+
#[doc(alias = "AMediaCodecCryptoInfo_getNumSubSamples")]
80+
pub fn num_sub_samples(&self) -> usize {
81+
unsafe { ffi::AMediaCodecCryptoInfo_getNumSubSamples(self.inner.as_ptr()) }
82+
}
83+
84+
/// A 16-byte opaque key.
85+
#[doc(alias = "AMediaCodecCryptoInfo_getKey")]
86+
pub fn key(&self) -> Result<[u8; 16]> {
87+
let mut key = [0u8; 16];
88+
let status =
89+
unsafe { ffi::AMediaCodecCryptoInfo_getKey(self.inner.as_ptr(), key.as_mut_ptr()) };
90+
MediaError::from_status(status).map(|()| key)
91+
}
92+
93+
/// A 16-byte initialization vector.
94+
#[doc(alias = "AMediaCodecCryptoInfo_getIV")]
95+
pub fn iv(&self) -> Result<[u8; 16]> {
96+
let mut iv = [0u8; 16];
97+
let status =
98+
unsafe { ffi::AMediaCodecCryptoInfo_getIV(self.inner.as_ptr(), iv.as_mut_ptr()) };
99+
MediaError::from_status(status).map(|()| iv)
100+
}
101+
102+
/// The type of encryption that has been applied,
103+
/// one of AMEDIACODECRYPTOINFO_MODE_CLEAR or AMEDIACODECRYPTOINFO_MODE_AES_CTR.
104+
#[doc(alias = "AMediaCodecCryptoInfo_getMode")]
105+
pub fn mode(&self) -> ffi::cryptoinfo_mode_t {
106+
unsafe { ffi::AMediaCodecCryptoInfo_getMode(self.inner.as_ptr()) }
107+
}
108+
109+
/// The number of leading unencrypted bytes in each subsample.
110+
#[doc(alias = "AMediaCodecCryptoInfo_getClearBytes")]
111+
pub fn clear_bytes(&self) -> Result<usize> {
112+
let mut clear_bytes = MaybeUninit::uninit();
113+
114+
let status = unsafe {
115+
ffi::AMediaCodecCryptoInfo_getClearBytes(self.inner.as_ptr(), clear_bytes.as_mut_ptr())
116+
};
117+
MediaError::from_status(status).map(|()| unsafe { clear_bytes.assume_init() })
118+
}
119+
120+
/// The number of trailing encrypted bytes in each subsample.
121+
#[doc(alias = "AMediaCodecCryptoInfo_getEncryptedBytes")]
122+
pub fn encrypted_bytes(&self) -> Result<usize> {
123+
let mut encrypted_bytes = MaybeUninit::uninit();
124+
let status = unsafe {
125+
ffi::AMediaCodecCryptoInfo_getEncryptedBytes(
126+
self.inner.as_ptr(),
127+
encrypted_bytes.as_mut_ptr(),
128+
)
129+
};
130+
MediaError::from_status(status).map(|()| unsafe { encrypted_bytes.assume_init() })
131+
}
132+
}
133+
134+
impl Drop for MediaCodecCryptoInfo {
135+
/// Delete a [`MediaCodecCryptoInfo`] created previously with [`MediaCodecCryptoInfo::new()`], or
136+
/// obtained from [`super::media_extractor::MediaExtractor`].
137+
#[doc(alias = "AMediaCodecCryptoInfo_delete")]
138+
fn drop(&mut self) {
139+
let status = unsafe { ffi::AMediaCodecCryptoInfo_delete(self.inner.as_ptr()) };
140+
MediaError::from_status(status).unwrap()
141+
}
142+
}

ndk/src/media/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55

66
pub mod image_reader;
77
pub mod media_codec;
8+
pub mod media_codec_crypto;
89
pub mod media_format;

0 commit comments

Comments
 (0)