1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use crate::codecs::Decoder;
16 use crate::codecs::DecoderConfig;
17 use crate::decoder::Category;
18 use crate::image::Image;
19 use crate::image::YuvRange;
20 use crate::internal_utils::pixels::*;
21 use crate::internal_utils::stream::IStream;
22 use crate::internal_utils::*;
23 use crate::*;
24 
25 use ndk_sys::bindings::*;
26 
27 use std::ffi::CString;
28 use std::os::raw::c_char;
29 use std::ptr;
30 
31 #[cfg(android_soong)]
32 include!(concat!(env!("OUT_DIR"), "/mediaimage2_bindgen.rs"));
33 
34 #[derive(Debug)]
35 struct MediaFormat {
36     format: *mut AMediaFormat,
37 }
38 
39 macro_rules! c_str {
40     ($var: ident, $var_tmp:ident, $str:expr) => {
41         let $var_tmp = CString::new($str).unwrap();
42         let $var = $var_tmp.as_ptr();
43     };
44 }
45 
46 #[derive(Debug, Default)]
47 struct PlaneInfo {
48     color_format: AndroidMediaCodecOutputColorFormat,
49     offset: [isize; 3],
50     row_stride: [u32; 3],
51     column_stride: [u32; 3],
52 }
53 
54 impl PlaneInfo {
pixel_format(&self) -> PixelFormat55     fn pixel_format(&self) -> PixelFormat {
56         match self.color_format {
57             AndroidMediaCodecOutputColorFormat::P010 => PixelFormat::AndroidP010,
58             AndroidMediaCodecOutputColorFormat::Yuv420Flexible => {
59                 let u_before_v = self.offset[2] == self.offset[1] + 1;
60                 let v_before_u = self.offset[1] == self.offset[2] + 1;
61                 let is_nv_format = self.column_stride == [1, 2, 2] && (u_before_v || v_before_u);
62                 match (is_nv_format, u_before_v) {
63                     (true, true) => PixelFormat::AndroidNv12,
64                     (true, false) => PixelFormat::AndroidNv21,
65                     (false, _) => PixelFormat::Yuv420,
66                 }
67             }
68         }
69     }
70 
depth(&self) -> u871     fn depth(&self) -> u8 {
72         match self.color_format {
73             AndroidMediaCodecOutputColorFormat::P010 => 16,
74             AndroidMediaCodecOutputColorFormat::Yuv420Flexible => 8,
75         }
76     }
77 }
78 
79 impl MediaFormat {
get_i32(&self, key: *const c_char) -> Option<i32>80     fn get_i32(&self, key: *const c_char) -> Option<i32> {
81         let mut value: i32 = 0;
82         match unsafe { AMediaFormat_getInt32(self.format, key, &mut value as *mut _) } {
83             true => Some(value),
84             false => None,
85         }
86     }
87 
get_i32_from_str(&self, key: &str) -> Option<i32>88     fn get_i32_from_str(&self, key: &str) -> Option<i32> {
89         c_str!(key_str, key_str_tmp, key);
90         self.get_i32(key_str)
91     }
92 
width(&self) -> AvifResult<i32>93     fn width(&self) -> AvifResult<i32> {
94         self.get_i32(unsafe { AMEDIAFORMAT_KEY_WIDTH })
95             .ok_or(AvifError::UnknownError("".into()))
96     }
97 
height(&self) -> AvifResult<i32>98     fn height(&self) -> AvifResult<i32> {
99         self.get_i32(unsafe { AMEDIAFORMAT_KEY_HEIGHT })
100             .ok_or(AvifError::UnknownError("".into()))
101     }
102 
slice_height(&self) -> AvifResult<i32>103     fn slice_height(&self) -> AvifResult<i32> {
104         self.get_i32(unsafe { AMEDIAFORMAT_KEY_SLICE_HEIGHT })
105             .ok_or(AvifError::UnknownError("".into()))
106     }
107 
stride(&self) -> AvifResult<i32>108     fn stride(&self) -> AvifResult<i32> {
109         self.get_i32(unsafe { AMEDIAFORMAT_KEY_STRIDE })
110             .ok_or(AvifError::UnknownError("".into()))
111     }
112 
color_format(&self) -> AvifResult<i32>113     fn color_format(&self) -> AvifResult<i32> {
114         self.get_i32(unsafe { AMEDIAFORMAT_KEY_COLOR_FORMAT })
115             .ok_or(AvifError::UnknownError("".into()))
116     }
117 
color_range(&self) -> YuvRange118     fn color_range(&self) -> YuvRange {
119         // color-range is documented but isn't exposed as a constant in the NDK:
120         // https://developer.android.com/reference/android/media/MediaFormat#KEY_COLOR_RANGE
121         let color_range = self.get_i32_from_str("color-range").unwrap_or(2);
122         if color_range == 0 {
123             YuvRange::Limited
124         } else {
125             YuvRange::Full
126         }
127     }
128 
guess_plane_info(&self) -> AvifResult<PlaneInfo>129     fn guess_plane_info(&self) -> AvifResult<PlaneInfo> {
130         let height = self.height()?;
131         let slice_height = self.slice_height().unwrap_or(height);
132         let stride = self.stride()?;
133         let color_format: AndroidMediaCodecOutputColorFormat = self.color_format()?.into();
134         let mut plane_info = PlaneInfo {
135             color_format,
136             ..Default::default()
137         };
138         match color_format {
139             AndroidMediaCodecOutputColorFormat::P010 => {
140                 plane_info.row_stride = [
141                     u32_from_i32(stride)?,
142                     u32_from_i32(stride)?,
143                     0, // V plane is not used for P010.
144                 ];
145                 plane_info.column_stride = [
146                     2, 2, 0, // V plane is not used for P010.
147                 ];
148                 plane_info.offset = [
149                     0,
150                     isize_from_i32(stride * slice_height)?,
151                     0, // V plane is not used for P010.
152                 ];
153             }
154             AndroidMediaCodecOutputColorFormat::Yuv420Flexible => {
155                 plane_info.row_stride = [
156                     u32_from_i32(stride)?,
157                     u32_from_i32((stride + 1) / 2)?,
158                     u32_from_i32((stride + 1) / 2)?,
159                 ];
160                 plane_info.column_stride = [1, 1, 1];
161                 plane_info.offset[0] = 0;
162                 plane_info.offset[1] = isize_from_i32(stride * slice_height)?;
163                 let u_plane_size = isize_from_i32(((stride + 1) / 2) * ((height + 1) / 2))?;
164                 // When color format is YUV_420_FLEXIBLE, the V plane comes before the U plane.
165                 plane_info.offset[2] = plane_info.offset[1] - u_plane_size;
166             }
167         }
168         Ok(plane_info)
169     }
170 
get_plane_info(&self) -> AvifResult<PlaneInfo>171     fn get_plane_info(&self) -> AvifResult<PlaneInfo> {
172         // When not building for the Android platform, image-data is not available, so simply try to
173         // guess the buffer format based on the available keys in the format.
174         #[cfg(not(android_soong))]
175         return self.guess_plane_info();
176 
177         #[cfg(android_soong)]
178         {
179             c_str!(key_str, key_str_tmp, "image-data");
180             let mut data: *mut std::ffi::c_void = ptr::null_mut();
181             let mut size: usize = 0;
182             if !unsafe {
183                 AMediaFormat_getBuffer(
184                     self.format,
185                     key_str,
186                     &mut data as *mut _,
187                     &mut size as *mut _,
188                 )
189             } {
190                 return self.guess_plane_info();
191             }
192             if size != std::mem::size_of::<android_MediaImage2>() {
193                 return self.guess_plane_info();
194             }
195             let image_data = unsafe { *(data as *const android_MediaImage2) };
196             if image_data.mType != android_MediaImage2_Type_MEDIA_IMAGE_TYPE_YUV {
197                 return self.guess_plane_info();
198             }
199             let planes = unsafe { ptr::read_unaligned(ptr::addr_of!(image_data.mPlane)) };
200             let mut plane_info = PlaneInfo {
201                 color_format: self.color_format()?.into(),
202                 ..Default::default()
203             };
204             for plane_index in 0usize..3 {
205                 plane_info.offset[plane_index] = isize_from_u32(planes[plane_index].mOffset)?;
206                 plane_info.row_stride[plane_index] = u32_from_i32(planes[plane_index].mRowInc)?;
207                 plane_info.column_stride[plane_index] = u32_from_i32(planes[plane_index].mColInc)?;
208             }
209             return Ok(plane_info);
210         }
211     }
212 }
213 
214 enum CodecInitializer {
215     ByName(String),
216     ByMimeType(String),
217 }
218 
219 #[cfg(android_soong)]
prefer_hardware_decoder(config: &DecoderConfig) -> bool220 fn prefer_hardware_decoder(config: &DecoderConfig) -> bool {
221     let prefer_hw = rustutils::system_properties::read_bool(
222         "media.stagefright.thumbnail.prefer_hw_codecs",
223         false,
224     )
225     .unwrap_or(false);
226     if config.codec_config.is_avif() {
227         // We will return true when all of the below conditions are true:
228         // 1) prefer_hw is true.
229         // 2) category is not Alpha and category is not Gainmap. We do not prefer hardware for
230         //    decoding these categories since they generally tend to be monochrome images and using
231         //    hardware for that is unreliable.
232         // 3) profile is 0. As of Sep 2024, there are no AV1 hardware decoders that support
233         //    anything other than profile 0.
234         prefer_hw
235             && config.category != Category::Alpha
236             && config.category != Category::Gainmap
237             && config.codec_config.profile() == 0
238     } else {
239         // We will return true when one of the following conditions are true:
240         // 1) prefer_hw is true.
241         // 2) depth is greater than 8. As of Nov 2024, the default HEVC software decoder on Android
242         //    only supports 8-bit images.
243         prefer_hw || config.depth > 8
244     }
245 }
246 
get_codec_initializers(config: &DecoderConfig) -> Vec<CodecInitializer>247 fn get_codec_initializers(config: &DecoderConfig) -> Vec<CodecInitializer> {
248     #[cfg(android_soong)]
249     {
250         // Use a specific decoder if it is requested.
251         if let Ok(Some(decoder)) =
252             rustutils::system_properties::read("media.crabbyavif.debug.decoder")
253         {
254             if !decoder.is_empty() {
255                 return vec![CodecInitializer::ByName(decoder)];
256             }
257         }
258     }
259     let dav1d = String::from("c2.android.av1-dav1d.decoder");
260     let gav1 = String::from("c2.android.av1.decoder");
261     let hevc = String::from("c2.android.hevc.decoder");
262     // As of Sep 2024, c2.android.av1.decoder is the only known decoder to support 12-bit AV1. So
263     // prefer that for 12 bit images.
264     let prefer_gav1 = config.depth == 12;
265     let is_avif = config.codec_config.is_avif();
266     let mime_type = if is_avif { MediaCodec::AV1_MIME } else { MediaCodec::HEVC_MIME };
267     let prefer_hw = false;
268     #[cfg(android_soong)]
269     let prefer_hw = prefer_hardware_decoder(config);
270     match (prefer_hw, is_avif, prefer_gav1) {
271         (true, false, _) => vec![
272             CodecInitializer::ByMimeType(mime_type.to_string()),
273             CodecInitializer::ByName(hevc),
274         ],
275         (false, false, _) => vec![
276             CodecInitializer::ByName(hevc),
277             CodecInitializer::ByMimeType(mime_type.to_string()),
278         ],
279         (true, true, true) => vec![
280             CodecInitializer::ByName(gav1),
281             CodecInitializer::ByMimeType(mime_type.to_string()),
282             CodecInitializer::ByName(dav1d),
283         ],
284         (true, true, false) => vec![
285             CodecInitializer::ByMimeType(mime_type.to_string()),
286             CodecInitializer::ByName(dav1d),
287             CodecInitializer::ByName(gav1),
288         ],
289         (false, true, true) => vec![
290             CodecInitializer::ByName(gav1),
291             CodecInitializer::ByName(dav1d),
292             CodecInitializer::ByMimeType(mime_type.to_string()),
293         ],
294         (false, true, false) => vec![
295             CodecInitializer::ByName(dav1d),
296             CodecInitializer::ByName(gav1),
297             CodecInitializer::ByMimeType(mime_type.to_string()),
298         ],
299     }
300 }
301 
302 #[derive(Default)]
303 pub struct MediaCodec {
304     codec: Option<*mut AMediaCodec>,
305     format: Option<MediaFormat>,
306     output_buffer_index: Option<usize>,
307     config: Option<DecoderConfig>,
308 }
309 
310 impl MediaCodec {
311     const AV1_MIME: &str = "video/av01";
312     const HEVC_MIME: &str = "video/hevc";
313 }
314 
315 impl Decoder for MediaCodec {
initialize(&mut self, config: &DecoderConfig) -> AvifResult<()>316     fn initialize(&mut self, config: &DecoderConfig) -> AvifResult<()> {
317         if self.codec.is_some() {
318             return Ok(()); // Already initialized.
319         }
320         let format = unsafe { AMediaFormat_new() };
321         if format.is_null() {
322             return Err(AvifError::UnknownError("".into()));
323         }
324         c_str!(
325             mime_type,
326             mime_type_tmp,
327             if config.codec_config.is_avif() { Self::AV1_MIME } else { Self::HEVC_MIME }
328         );
329         unsafe {
330             AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, mime_type);
331             AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, i32_from_u32(config.width)?);
332             AMediaFormat_setInt32(
333                 format,
334                 AMEDIAFORMAT_KEY_HEIGHT,
335                 i32_from_u32(config.height)?,
336             );
337             AMediaFormat_setInt32(
338                 format,
339                 AMEDIAFORMAT_KEY_COLOR_FORMAT,
340                 if config.depth == 8 {
341                     AndroidMediaCodecOutputColorFormat::Yuv420Flexible
342                 } else {
343                     AndroidMediaCodecOutputColorFormat::P010
344                 } as i32,
345             );
346             // low-latency is documented but isn't exposed as a constant in the NDK:
347             // https://developer.android.com/reference/android/media/MediaFormat#KEY_LOW_LATENCY
348             c_str!(low_latency, low_latency_tmp, "low-latency");
349             AMediaFormat_setInt32(format, low_latency, 1);
350             AMediaFormat_setInt32(
351                 format,
352                 AMEDIAFORMAT_KEY_MAX_INPUT_SIZE,
353                 i32_from_usize(config.max_input_size)?,
354             );
355             let codec_specific_data = config.codec_config.raw_data();
356             if !codec_specific_data.is_empty() {
357                 AMediaFormat_setBuffer(
358                     format,
359                     AMEDIAFORMAT_KEY_CSD_0,
360                     codec_specific_data.as_ptr() as *const _,
361                     codec_specific_data.len(),
362                 );
363             }
364         }
365 
366         let mut codec = ptr::null_mut();
367         for codec_initializer in get_codec_initializers(config) {
368             codec = match codec_initializer {
369                 CodecInitializer::ByName(name) => {
370                     c_str!(codec_name, codec_name_tmp, name.as_str());
371                     unsafe { AMediaCodec_createCodecByName(codec_name) }
372                 }
373                 CodecInitializer::ByMimeType(mime_type) => {
374                     c_str!(codec_mime, codec_mime_tmp, mime_type.as_str());
375                     unsafe { AMediaCodec_createDecoderByType(codec_mime) }
376                 }
377             };
378             if codec.is_null() {
379                 continue;
380             }
381             let status = unsafe {
382                 AMediaCodec_configure(codec, format, ptr::null_mut(), ptr::null_mut(), 0)
383             };
384             if status != media_status_t_AMEDIA_OK {
385                 unsafe {
386                     AMediaCodec_delete(codec);
387                 }
388                 codec = ptr::null_mut();
389                 continue;
390             }
391             let status = unsafe { AMediaCodec_start(codec) };
392             if status != media_status_t_AMEDIA_OK {
393                 unsafe {
394                     AMediaCodec_delete(codec);
395                 }
396                 codec = ptr::null_mut();
397                 continue;
398             }
399             break;
400         }
401         if codec.is_null() {
402             unsafe { AMediaFormat_delete(format) };
403             return Err(AvifError::NoCodecAvailable);
404         }
405         self.codec = Some(codec);
406         self.config = Some(config.clone());
407         Ok(())
408     }
409 
get_next_image( &mut self, payload: &[u8], _spatial_id: u8, image: &mut Image, category: Category, ) -> AvifResult<()>410     fn get_next_image(
411         &mut self,
412         payload: &[u8],
413         _spatial_id: u8,
414         image: &mut Image,
415         category: Category,
416     ) -> AvifResult<()> {
417         if self.codec.is_none() {
418             self.initialize(&DecoderConfig::default())?;
419         }
420         let codec = self.codec.unwrap();
421         if self.output_buffer_index.is_some() {
422             // Release any existing output buffer.
423             unsafe {
424                 AMediaCodec_releaseOutputBuffer(codec, self.output_buffer_index.unwrap(), false);
425             }
426         }
427         let mut retry_count = 0;
428         unsafe {
429             while retry_count < 100 {
430                 retry_count += 1;
431                 let input_index = AMediaCodec_dequeueInputBuffer(codec, 10000);
432                 if input_index >= 0 {
433                     let mut input_buffer_size: usize = 0;
434                     let input_buffer = AMediaCodec_getInputBuffer(
435                         codec,
436                         input_index as usize,
437                         &mut input_buffer_size as *mut _,
438                     );
439                     if input_buffer.is_null() {
440                         return Err(AvifError::UnknownError(format!(
441                             "input buffer at index {input_index} was null"
442                         )));
443                     }
444                     let hevc_whole_nal_units = self.hevc_whole_nal_units(payload)?;
445                     let codec_payload = match &hevc_whole_nal_units {
446                         Some(hevc_payload) => hevc_payload,
447                         None => payload,
448                     };
449                     if input_buffer_size < codec_payload.len() {
450                         return Err(AvifError::UnknownError(format!(
451                         "input buffer (size {input_buffer_size}) was not big enough. required size: {}",
452                         codec_payload.len()
453                     )));
454                     }
455                     ptr::copy_nonoverlapping(
456                         codec_payload.as_ptr(),
457                         input_buffer,
458                         codec_payload.len(),
459                     );
460 
461                     if AMediaCodec_queueInputBuffer(
462                         codec,
463                         usize_from_isize(input_index)?,
464                         /*offset=*/ 0,
465                         codec_payload.len(),
466                         /*pts=*/ 0,
467                         /*flags=*/ 0,
468                     ) != media_status_t_AMEDIA_OK
469                     {
470                         return Err(AvifError::UnknownError("".into()));
471                     }
472                     break;
473                 } else if input_index == AMEDIACODEC_INFO_TRY_AGAIN_LATER as isize {
474                     continue;
475                 } else {
476                     return Err(AvifError::UnknownError(format!(
477                         "got input index < 0: {input_index}"
478                     )));
479                 }
480             }
481         }
482         let mut buffer: Option<*mut u8> = None;
483         let mut buffer_size: usize = 0;
484         let mut buffer_info = AMediaCodecBufferInfo::default();
485         retry_count = 0;
486         while retry_count < 100 {
487             retry_count += 1;
488             unsafe {
489                 let output_index =
490                     AMediaCodec_dequeueOutputBuffer(codec, &mut buffer_info as *mut _, 10000);
491                 if output_index >= 0 {
492                     let output_buffer = AMediaCodec_getOutputBuffer(
493                         codec,
494                         usize_from_isize(output_index)?,
495                         &mut buffer_size as *mut _,
496                     );
497                     if output_buffer.is_null() {
498                         return Err(AvifError::UnknownError("output buffer is null".into()));
499                     }
500                     buffer = Some(output_buffer);
501                     self.output_buffer_index = Some(usize_from_isize(output_index)?);
502                     break;
503                 } else if output_index == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED as isize {
504                     continue;
505                 } else if output_index == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED as isize {
506                     let format = AMediaCodec_getOutputFormat(codec);
507                     if format.is_null() {
508                         return Err(AvifError::UnknownError("output format was null".into()));
509                     }
510                     self.format = Some(MediaFormat { format });
511                     continue;
512                 } else if output_index == AMEDIACODEC_INFO_TRY_AGAIN_LATER as isize {
513                     continue;
514                 } else {
515                     return Err(AvifError::UnknownError(format!(
516                         "mediacodec dequeue_output_buffer failed: {output_index}"
517                     )));
518                 }
519             }
520         }
521         if buffer.is_none() {
522             return Err(AvifError::UnknownError(
523                 "did not get buffer from mediacodec".into(),
524             ));
525         }
526         if self.format.is_none() {
527             return Err(AvifError::UnknownError("format is none".into()));
528         }
529         let buffer = buffer.unwrap();
530         let format = self.format.unwrap_ref();
531         image.width = format.width()? as u32;
532         image.height = format.height()? as u32;
533         image.yuv_range = format.color_range();
534         let plane_info = format.get_plane_info()?;
535         image.depth = plane_info.depth();
536         image.yuv_format = plane_info.pixel_format();
537         match category {
538             Category::Alpha => {
539                 // TODO: make sure alpha plane matches previous alpha plane.
540                 image.row_bytes[3] = plane_info.row_stride[0];
541                 image.planes[3] = Some(Pixels::from_raw_pointer(
542                     unsafe { buffer.offset(plane_info.offset[0]) },
543                     image.depth as u32,
544                     image.height,
545                     image.row_bytes[3],
546                 )?);
547             }
548             _ => {
549                 image.chroma_sample_position = ChromaSamplePosition::Unknown;
550                 image.color_primaries = ColorPrimaries::Unspecified;
551                 image.transfer_characteristics = TransferCharacteristics::Unspecified;
552                 image.matrix_coefficients = MatrixCoefficients::Unspecified;
553 
554                 for i in 0usize..3 {
555                     if i == 2
556                         && matches!(
557                             image.yuv_format,
558                             PixelFormat::AndroidP010
559                                 | PixelFormat::AndroidNv12
560                                 | PixelFormat::AndroidNv21
561                         )
562                     {
563                         // V plane is not needed for these formats.
564                         break;
565                     }
566                     image.row_bytes[i] = plane_info.row_stride[i];
567                     let plane_height = if i == 0 { image.height } else { (image.height + 1) / 2 };
568                     image.planes[i] = Some(Pixels::from_raw_pointer(
569                         unsafe { buffer.offset(plane_info.offset[i]) },
570                         image.depth as u32,
571                         plane_height,
572                         image.row_bytes[i],
573                     )?);
574                 }
575             }
576         }
577         Ok(())
578     }
579 }
580 
581 impl MediaCodec {
hevc_whole_nal_units(&self, payload: &[u8]) -> AvifResult<Option<Vec<u8>>>582     fn hevc_whole_nal_units(&self, payload: &[u8]) -> AvifResult<Option<Vec<u8>>> {
583         if !self.config.unwrap_ref().codec_config.is_heic() {
584             return Ok(None);
585         }
586         // For HEVC, MediaCodec expects whole NAL units with each unit prefixed with a start code
587         // of "\x00\x00\x00\x01".
588         let nal_length_size = self.config.unwrap_ref().codec_config.nal_length_size() as usize;
589         let mut offset = 0;
590         let mut hevc_payload = Vec::new();
591         while offset < payload.len() {
592             let payload_slice = &payload[offset..];
593             let mut stream = IStream::create(payload_slice);
594             let nal_length = usize_from_u64(stream.read_uxx(nal_length_size as u8)?)?;
595             let nal_unit_end = checked_add!(nal_length, nal_length_size)?;
596             let nal_unit_range = nal_length_size..nal_unit_end;
597             check_slice_range(payload_slice.len(), &nal_unit_range)?;
598             // Start code.
599             hevc_payload.extend_from_slice(&[0, 0, 0, 1]);
600             // NAL Unit.
601             hevc_payload.extend_from_slice(&payload_slice[nal_unit_range]);
602             offset = checked_add!(offset, nal_unit_end)?;
603         }
604         Ok(Some(hevc_payload))
605     }
606 }
607 
608 impl Drop for MediaFormat {
drop(&mut self)609     fn drop(&mut self) {
610         unsafe { AMediaFormat_delete(self.format) };
611     }
612 }
613 
614 impl Drop for MediaCodec {
drop(&mut self)615     fn drop(&mut self) {
616         if self.codec.is_some() {
617             if self.output_buffer_index.is_some() {
618                 unsafe {
619                     AMediaCodec_releaseOutputBuffer(
620                         self.codec.unwrap(),
621                         self.output_buffer_index.unwrap(),
622                         false,
623                     );
624                 }
625                 self.output_buffer_index = None;
626             }
627             unsafe {
628                 AMediaCodec_stop(self.codec.unwrap());
629                 AMediaCodec_delete(self.codec.unwrap());
630             }
631             self.codec = None;
632         }
633         self.format = None;
634     }
635 }
636