1use std::ffi::c_void;
2use std::ptr;
3
4use crate::error::{Error, Result};
5use crate::ffi::{check_decoder, decoder_version};
6use crate::util::{AlignedBuffer, VersionInfo};
7
8const IA_DRC_DEC_CONFIG_PARAM_PCM_WDSZ: i32 = 0x0000;
9const IA_DRC_DEC_CONFIG_PARAM_SAMP_FREQ: i32 = 0x0001;
10const IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS: i32 = 0x0002;
11const IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT: i32 = 0x0007;
12const IA_DRC_DEC_CONFIG_PARAM_INT_PRESENT: i32 = 0x0008;
13const IA_DRC_DEC_CONFIG_PARAM_FRAME_SIZE: i32 = 0x000E;
14const IA_DRC_DEC_CONFIG_GAIN_STREAM_FLAG: i32 = 0x0010;
15const IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE: i32 = 0x0011;
16const IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS: i32 = 0x0012;
17const IA_DRC_DEC_CONFIG_DRC_LOUD_NORM: i32 = 0x0013;
18const IA_DRC_DEC_CONFIG_PARAM_APPLY_CROSSFADE: i32 = 0x0017;
19const IA_DRC_DEC_CONFIG_PARAM_CONFIG_CHANGED: i32 = 0x0018;
20const IA_DRC_DEC_CONFIG_DRC_LOUDNESS_LEVELING: i32 = 0x0019;
21const IA_CMD_TYPE_INIT_CPY_BSF_BUFF: i32 = 0x0201;
22const IA_CMD_TYPE_INIT_CPY_IC_BSF_BUFF: i32 = 0x0202;
23const IA_CMD_TYPE_INIT_CPY_IL_BSF_BUFF: i32 = 0x0203;
24const IA_CMD_TYPE_INIT_CPY_IN_BSF_BUFF: i32 = 0x0205;
25const IA_XHEAAC_DEC_CONFIG_PARAM_DRC_LOUDNESS_LEVELING: i32 = 0x0029;
26const DECODER_MIN_INIT_BYTES: usize = 256;
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum DecoderTransport {
30 Auto,
31 Raw,
32 Mp4Raw,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum DrcEffectType {
37 None,
38 Night,
39 Noisy,
40 Limited,
41 LowLevel,
42 Dialog,
43 GeneralCompression,
44 Expanded,
45 Articulated,
46 Headphone,
47 PortableSpeaker,
48 StereoDownmix,
49}
50
51impl DrcEffectType {
52 fn raw(self) -> i32 {
53 match self {
54 Self::None => 0,
55 Self::Night => 1,
56 Self::Noisy => 2,
57 Self::Limited => 3,
58 Self::LowLevel => 4,
59 Self::Dialog => 5,
60 Self::GeneralCompression => 6,
61 Self::Expanded => 7,
62 Self::Articulated => 8,
63 Self::Headphone => 9,
64 Self::PortableSpeaker => 10,
65 Self::StereoDownmix => 11,
66 }
67 }
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum SbrMode {
72 Unknown,
73 Disabled,
74 Enabled,
75 Downsampled,
76 Esbr,
77}
78
79impl SbrMode {
80 fn frame_samples(self) -> u32 {
81 match self {
82 Self::Enabled => 2048,
83 Self::Esbr => 4096,
84 _ => 1024,
85 }
86 }
87}
88
89impl From<i32> for SbrMode {
90 fn from(value: i32) -> Self {
91 match value {
92 0 => Self::Disabled,
93 1 => Self::Enabled,
94 2 => Self::Downsampled,
95 3 => Self::Esbr,
96 _ => Self::Unknown,
97 }
98 }
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102pub enum ChannelMode {
103 Mono,
104 Stereo,
105 DualMono,
106 ParametricStereo,
107 Unknown(i32),
108}
109
110impl From<i32> for ChannelMode {
111 fn from(value: i32) -> Self {
112 match value {
113 0 => Self::Mono,
114 1 => Self::Stereo,
115 2 => Self::DualMono,
116 3 => Self::ParametricStereo,
117 other => Self::Unknown(other),
118 }
119 }
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123pub struct RawStreamConfig {
124 pub sample_rate: u32,
125 pub audio_object_type: ProfileHint,
126}
127
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129pub enum ProfileHint {
130 AacLc,
131 HeAacV1,
132 AacLd,
133 HeAacV2,
134 AacEld,
135 Usac,
136}
137
138impl ProfileHint {
139 fn aot(self) -> i32 {
140 match self {
141 Self::AacLc => libxaac_sys::AOT_AAC_LC as i32,
142 Self::HeAacV1 => libxaac_sys::AOT_SBR as i32,
143 Self::AacLd => libxaac_sys::AOT_AAC_LD as i32,
144 Self::HeAacV2 => libxaac_sys::AOT_PS as i32,
145 Self::AacEld => libxaac_sys::AOT_AAC_ELD as i32,
146 Self::Usac => libxaac_sys::AOT_USAC as i32,
147 }
148 }
149}
150
151#[derive(Debug, Clone, PartialEq)]
152pub struct DecoderDrcConfig {
153 pub enabled: bool,
154 pub cut: f32,
155 pub boost: f32,
156 pub target_level: u8,
157 pub heavy_compression: bool,
158 pub effect_type: DrcEffectType,
159 pub target_loudness: Option<i32>,
160 pub loudness_leveling: Option<bool>,
161}
162
163impl Default for DecoderDrcConfig {
164 fn default() -> Self {
165 Self {
166 enabled: true,
167 cut: 1.0,
168 boost: 1.0,
169 target_level: 108,
170 heavy_compression: false,
171 effect_type: DrcEffectType::None,
172 target_loudness: None,
173 loudness_leveling: None,
174 }
175 }
176}
177
178#[derive(Debug, Clone)]
179pub struct DecoderConfig {
180 pub transport: DecoderTransport,
181 pub pcm_word_size: u16,
182 pub raw: Option<RawStreamConfig>,
183 pub downmix_to_mono: bool,
184 pub to_stereo: bool,
185 pub downsample_sbr: bool,
186 pub max_channels: u8,
187 pub coupling_channels: u8,
188 pub downmix_to_stereo: bool,
189 pub disable_sync: bool,
190 pub auto_sbr_upsample: bool,
191 pub ld_frame_480: bool,
192 pub hq_esbr: bool,
193 pub ps_enable: bool,
194 pub peak_limiter: bool,
195 pub frame_length_960: bool,
196 pub error_concealment: bool,
197 pub enable_esbr: bool,
198 pub drc: DecoderDrcConfig,
199}
200
201impl Default for DecoderConfig {
202 fn default() -> Self {
203 Self {
204 transport: DecoderTransport::Auto,
205 pcm_word_size: 16,
206 raw: None,
207 downmix_to_mono: false,
208 to_stereo: false,
209 downsample_sbr: false,
210 max_channels: 2,
211 coupling_channels: 0,
212 downmix_to_stereo: false,
213 disable_sync: false,
214 auto_sbr_upsample: true,
215 ld_frame_480: false,
216 hq_esbr: false,
217 ps_enable: false,
218 peak_limiter: true,
219 frame_length_960: false,
220 error_concealment: true,
221 enable_esbr: false,
222 drc: DecoderDrcConfig::default(),
223 }
224 }
225}
226
227impl DecoderConfig {
228 fn validate(&self) -> Result<()> {
229 if !matches!(self.pcm_word_size, 16 | 24) {
230 return Err(Error::InvalidConfig("pcm_word_size must be 16 or 24"));
231 }
232 if self.max_channels == 0 {
233 return Err(Error::InvalidConfig(
234 "max_channels must be greater than zero",
235 ));
236 }
237 if matches!(
238 self.transport,
239 DecoderTransport::Raw | DecoderTransport::Mp4Raw
240 ) && self.raw.is_none()
241 {
242 return Err(Error::InvalidConfig(
243 "raw transport requires RawStreamConfig",
244 ));
245 }
246 Ok(())
247 }
248}
249
250#[derive(Debug, Clone, PartialEq, Eq)]
251pub struct StreamInfo {
252 pub sample_rate: u32,
253 pub channels: u16,
254 pub channel_mask: u32,
255 pub channel_mode: Option<ChannelMode>,
256 pub pcm_word_size: u16,
257 pub sbr_mode: SbrMode,
258 pub audio_object_type: i32,
259 pub drc_effect_type: Option<DrcEffectType>,
260 pub drc_target_loudness: Option<i32>,
261 pub drc_loudness_norm: Option<i32>,
262 pub loudness_leveling: Option<bool>,
263 pub preroll_frames: Option<u32>,
264 pub drc_config_changed: Option<bool>,
265 pub drc_apply_crossfade: Option<bool>,
266 pub extension_elements: Option<u32>,
267 pub config_extensions: Option<u32>,
268 pub gain_payload_len: Option<u32>,
269 pub drc_active: bool,
270}
271
272#[derive(Debug, Clone, PartialEq, Eq)]
273pub struct DecodeProgress {
274 pub initialized: bool,
275 pub stream_info: Option<StreamInfo>,
276}
277
278#[derive(Debug, Clone, PartialEq, Eq)]
279pub enum DecodeStatus {
280 Frame(DecodedFrame),
281 NeedMoreInput(DecodeProgress),
282 EndOfStream,
283}
284
285#[derive(Debug, Clone, PartialEq, Eq)]
286pub struct DecodedFrame {
287 pub pcm: Vec<u8>,
288 pub bytes_consumed: usize,
289 pub stream_info: StreamInfo,
290}
291
292impl DecodedFrame {
293 pub fn pcm_i16(&self) -> Option<Vec<i16>> {
294 if self.stream_info.pcm_word_size != 16 || self.pcm.len() % 2 != 0 {
295 return None;
296 }
297
298 Some(
299 self.pcm
300 .chunks_exact(2)
301 .map(|chunk| i16::from_le_bytes([chunk[0], chunk[1]]))
302 .collect(),
303 )
304 }
305
306 pub fn pcm_i24(&self) -> Option<Vec<i32>> {
307 if self.stream_info.pcm_word_size != 24 || self.pcm.len() % 3 != 0 {
308 return None;
309 }
310
311 Some(
312 self.pcm
313 .chunks_exact(3)
314 .map(|chunk| {
315 let value = i32::from(chunk[0])
316 | (i32::from(chunk[1]) << 8)
317 | (i32::from(chunk[2]) << 16);
318 if (value & 0x0080_0000) != 0 {
319 value | !0x00ff_ffff
320 } else {
321 value
322 }
323 })
324 .collect(),
325 )
326 }
327}
328
329#[derive(Debug)]
330struct DrcDecoder {
331 api: AlignedBuffer,
332 memtabs: AlignedBuffer,
333 memblocks: Vec<AlignedBuffer>,
334 input_index: usize,
335 output_index: usize,
336}
337
338impl DrcDecoder {
339 fn new(stream_info: &StreamInfo) -> Result<Self> {
340 let mut api_size = 0u32;
341 check_decoder(unsafe {
342 libxaac_sys::ia_drc_dec_api(
343 ptr::null_mut(),
344 libxaac_sys::IA_API_CMD_GET_API_SIZE as i32,
345 0,
346 (&mut api_size as *mut _) as *mut c_void,
347 )
348 })?;
349
350 let api = AlignedBuffer::new(api_size as usize, 8)?;
351 check_decoder(unsafe {
352 libxaac_sys::ia_drc_dec_api(
353 api.as_ptr().cast::<c_void>(),
354 libxaac_sys::IA_API_CMD_INIT as i32,
355 libxaac_sys::IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS as i32,
356 ptr::null_mut(),
357 )
358 })?;
359
360 let mut drc = Self {
361 api,
362 memtabs: AlignedBuffer::new(4, 4)?,
363 memblocks: Vec::new(),
364 input_index: 2,
365 output_index: 3,
366 };
367 drc.set_config(
368 IA_DRC_DEC_CONFIG_PARAM_SAMP_FREQ,
369 stream_info.sample_rate as i32,
370 )?;
371 drc.set_config(
372 IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS,
373 i32::from(stream_info.channels),
374 )?;
375 drc.set_config(
376 IA_DRC_DEC_CONFIG_PARAM_PCM_WDSZ,
377 i32::from(stream_info.pcm_word_size),
378 )?;
379 drc.set_config(
380 IA_DRC_DEC_CONFIG_PARAM_FRAME_SIZE,
381 stream_info.sbr_mode.frame_samples() as i32,
382 )?;
383 drc.allocate_memory()?;
384 Ok(drc)
385 }
386
387 fn allocate_memory(&mut self) -> Result<()> {
388 let mut memtabs_size = 0u32;
389 check_decoder(self.call_with_value(
390 libxaac_sys::IA_API_CMD_GET_MEMTABS_SIZE as i32,
391 0,
392 (&mut memtabs_size as *mut _) as *mut c_void,
393 ))?;
394 self.memtabs = AlignedBuffer::new(memtabs_size as usize, 8)?;
395 check_decoder(self.call_with_value(
396 libxaac_sys::IA_API_CMD_SET_MEMTABS_PTR as i32,
397 0,
398 self.memtabs.as_ptr().cast::<c_void>(),
399 ))?;
400 check_decoder(self.call(
401 libxaac_sys::IA_API_CMD_INIT as i32,
402 libxaac_sys::IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS as i32,
403 ptr::null_mut(),
404 ))?;
405
406 let mut mem_count = 0i32;
407 check_decoder(self.call_with_value(
408 libxaac_sys::IA_API_CMD_GET_N_MEMTABS as i32,
409 0,
410 (&mut mem_count as *mut _) as *mut c_void,
411 ))?;
412
413 for index in 0..mem_count {
414 let mut size = 0u32;
415 let mut alignment = 0u32;
416 check_decoder(self.call_with_value(
417 libxaac_sys::IA_API_CMD_GET_MEM_INFO_SIZE as i32,
418 index,
419 (&mut size as *mut _) as *mut c_void,
420 ))?;
421 check_decoder(self.call_with_value(
422 libxaac_sys::IA_API_CMD_GET_MEM_INFO_ALIGNMENT as i32,
423 index,
424 (&mut alignment as *mut _) as *mut c_void,
425 ))?;
426 let block = AlignedBuffer::new(size as usize, alignment.max(1) as usize)?;
427 check_decoder(self.call_with_value(
428 libxaac_sys::IA_API_CMD_SET_MEM_PTR as i32,
429 index,
430 block.as_ptr().cast::<c_void>(),
431 ))?;
432 self.memblocks.push(block);
433 }
434
435 Ok(())
436 }
437
438 fn sync_stream_info(&mut self, info: &StreamInfo) -> Result<()> {
439 self.set_config(
440 IA_DRC_DEC_CONFIG_PARAM_FRAME_SIZE,
441 info.sbr_mode.frame_samples() as i32,
442 )?;
443 self.set_config(IA_DRC_DEC_CONFIG_PARAM_SAMP_FREQ, info.sample_rate as i32)?;
444 self.set_config(
445 IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS,
446 i32::from(info.channels),
447 )?;
448 self.set_config(
449 IA_DRC_DEC_CONFIG_PARAM_PCM_WDSZ,
450 i32::from(info.pcm_word_size),
451 )?;
452 if let Some(loudness) = info.drc_target_loudness {
453 self.set_config(IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS, loudness)?;
454 }
455 if let Some(loud_norm) = info.drc_loudness_norm {
456 self.set_config(IA_DRC_DEC_CONFIG_DRC_LOUD_NORM, loud_norm)?;
457 }
458 if let Some(effect) = info.drc_effect_type {
459 self.set_config(IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE, effect.raw())?;
460 }
461 if let Some(leveling) = info.loudness_leveling {
462 self.set_config(IA_DRC_DEC_CONFIG_DRC_LOUDNESS_LEVELING, i32::from(leveling))?;
463 }
464 if let Some(changed) = info.drc_config_changed {
465 self.set_config(IA_DRC_DEC_CONFIG_PARAM_CONFIG_CHANGED, i32::from(changed))?;
466 }
467 if let Some(crossfade) = info.drc_apply_crossfade {
468 self.set_config(
469 IA_DRC_DEC_CONFIG_PARAM_APPLY_CROSSFADE,
470 i32::from(crossfade),
471 )?;
472 }
473 Ok(())
474 }
475
476 fn copy_split_payload(
477 &mut self,
478 input_len_cmd: i32,
479 init_cmd: i32,
480 payload: &[u8],
481 bits_format: i32,
482 ) -> Result<()> {
483 if payload.is_empty() {
484 return Ok(());
485 }
486 self.set_config(IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, bits_format)?;
487 self.copy_to_input(payload)?;
488 let mut size = payload.len() as i32;
489 check_decoder(self.call_with_value(
490 input_len_cmd,
491 0,
492 (&mut size as *mut _) as *mut c_void,
493 ))?;
494 check_decoder(self.call(
495 libxaac_sys::IA_API_CMD_INIT as i32,
496 init_cmd,
497 ptr::null_mut(),
498 ))
499 }
500
501 fn copy_to_input(&mut self, data: &[u8]) -> Result<()> {
502 let input = self
503 .memblocks
504 .get(self.input_index)
505 .ok_or(Error::InvalidConfig("drc input buffer missing"))?
506 .as_ptr();
507 let capacity = self.input_capacity();
508 if data.len() > capacity {
509 return Err(Error::InputTooLarge {
510 capacity,
511 actual: data.len(),
512 });
513 }
514 unsafe {
515 ptr::copy_nonoverlapping(data.as_ptr(), input, data.len());
516 if data.len() < capacity {
517 ptr::write_bytes(input.add(data.len()), 0, capacity - data.len());
518 }
519 }
520 Ok(())
521 }
522
523 fn input_capacity(&self) -> usize {
524 self.memblocks
525 .get(self.input_index)
526 .map(|_| {
527 self.query_mem_size(self.input_index as i32)
528 .unwrap_or_default() as usize
529 })
530 .unwrap_or_default()
531 }
532
533 fn output_capacity(&self) -> usize {
534 self.memblocks
535 .get(self.output_index)
536 .map(|_| {
537 self.query_mem_size(self.output_index as i32)
538 .unwrap_or_default() as usize
539 })
540 .unwrap_or_default()
541 }
542
543 fn process_pcm(
544 &mut self,
545 pcm: &[u8],
546 info: &StreamInfo,
547 gain_payload: Option<&[u8]>,
548 ) -> Result<Vec<u8>> {
549 self.sync_stream_info(info)?;
550 self.copy_to_input(pcm)?;
551 if let Some(gain_payload) = gain_payload.filter(|payload| !payload.is_empty()) {
552 self.set_config(IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, 1)?;
553 let gain_stream_flag = 1i32;
554 self.call_with_value(
555 libxaac_sys::IA_API_CMD_SET_INPUT_BYTES as i32,
556 0,
557 (&mut (pcm.len() as i32) as *mut _) as *mut c_void,
558 );
559 self.copy_to_input(gain_payload)?;
560 let mut gain_len = gain_payload.len() as i32;
561 check_decoder(self.call_with_value(
562 0x000B,
563 0,
564 (&mut gain_len as *mut _) as *mut c_void,
565 ))?;
566 self.set_config(IA_DRC_DEC_CONFIG_GAIN_STREAM_FLAG, gain_stream_flag)?;
567 check_decoder(self.call(
568 libxaac_sys::IA_API_CMD_INIT as i32,
569 IA_CMD_TYPE_INIT_CPY_BSF_BUFF,
570 ptr::null_mut(),
571 ))?;
572 self.copy_to_input(pcm)?;
573 }
574
575 let mut pcm_len = pcm.len() as i32;
576 check_decoder(self.call_with_value(
577 libxaac_sys::IA_API_CMD_SET_INPUT_BYTES as i32,
578 0,
579 (&mut pcm_len as *mut _) as *mut c_void,
580 ))?;
581 check_decoder(self.call(
582 libxaac_sys::IA_API_CMD_EXECUTE as i32,
583 libxaac_sys::IA_CMD_TYPE_DO_EXECUTE as i32,
584 ptr::null_mut(),
585 ))?;
586 let out = self
587 .memblocks
588 .get(self.output_index)
589 .ok_or(Error::InvalidConfig("drc output buffer missing"))?
590 .as_ptr();
591 let len = pcm.len().min(self.output_capacity());
592 Ok(unsafe { std::slice::from_raw_parts(out, len) }.to_vec())
593 }
594
595 fn query_mem_size(&self, index: i32) -> Result<u32> {
596 let mut size = 0u32;
597 check_decoder(self.call_with_value(
598 libxaac_sys::IA_API_CMD_GET_MEM_INFO_SIZE as i32,
599 index,
600 (&mut size as *mut _) as *mut c_void,
601 ))?;
602 Ok(size)
603 }
604
605 fn set_config(&mut self, index: i32, value: i32) -> Result<()> {
606 let mut value = value;
607 check_decoder(self.call_with_value(
608 libxaac_sys::IA_API_CMD_SET_CONFIG_PARAM as i32,
609 index,
610 (&mut value as *mut _) as *mut c_void,
611 ))
612 }
613
614 fn call(&self, cmd: i32, idx: i32, value: *mut c_void) -> i32 {
615 unsafe { libxaac_sys::ia_drc_dec_api(self.api.as_ptr().cast::<c_void>(), cmd, idx, value) }
616 }
617
618 fn call_with_value(&self, cmd: i32, idx: i32, value: *mut c_void) -> i32 {
619 self.call(cmd, idx, value)
620 }
621}
622
623#[derive(Debug)]
624pub struct Decoder {
625 config: DecoderConfig,
626 version: VersionInfo,
627 api: AlignedBuffer,
628 memtabs: AlignedBuffer,
629 memblocks: Vec<AlignedBuffer>,
630 input_index: usize,
631 output_index: usize,
632 input_capacity: usize,
633 initialized: bool,
634 input_over_signaled: bool,
635 finished: bool,
636 pending_input: Vec<u8>,
637 cached_info: Option<StreamInfo>,
638 drc_decoder: Option<DrcDecoder>,
639}
640
641impl Decoder {
642 pub fn new(config: DecoderConfig) -> Result<Self> {
643 config.validate()?;
644
645 let version = decoder_version();
646 let mut api_size = 0u32;
647 check_decoder(unsafe {
648 libxaac_sys::ixheaacd_dec_api(
649 ptr::null_mut(),
650 libxaac_sys::IA_API_CMD_GET_API_SIZE as i32,
651 0,
652 (&mut api_size as *mut _) as *mut c_void,
653 )
654 })?;
655
656 let api = AlignedBuffer::new(api_size as usize, 4)?;
657 check_decoder(unsafe {
658 libxaac_sys::ixheaacd_dec_api(
659 api.as_ptr().cast::<c_void>(),
660 libxaac_sys::IA_API_CMD_INIT as i32,
661 libxaac_sys::IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS as i32,
662 ptr::null_mut(),
663 )
664 })?;
665
666 let mut decoder = Self {
667 config,
668 version,
669 api,
670 memtabs: AlignedBuffer::new(4, 4)?,
671 memblocks: Vec::new(),
672 input_index: 0,
673 output_index: 0,
674 input_capacity: 0,
675 initialized: false,
676 input_over_signaled: false,
677 finished: false,
678 pending_input: Vec::new(),
679 cached_info: None,
680 drc_decoder: None,
681 };
682 decoder.apply_config()?;
683 decoder.allocate_memory()?;
684 Ok(decoder)
685 }
686
687 pub fn config(&self) -> &DecoderConfig {
688 &self.config
689 }
690
691 pub fn version(&self) -> &VersionInfo {
692 &self.version
693 }
694
695 pub fn input_capacity(&self) -> usize {
696 self.input_capacity
697 }
698
699 pub fn stream_info(&self) -> Option<&StreamInfo> {
700 self.cached_info.as_ref()
701 }
702
703 pub fn probe_stream_info(&mut self, data: &[u8]) -> Result<StreamInfo> {
704 if self.cached_info.is_some() {
705 return Ok(self.cached_info.clone().expect("cached stream info"));
706 }
707 self.pending_input.extend_from_slice(data);
708 loop {
709 match self.drive_initialization(data.is_empty())? {
710 InitState::Ready => return self.refresh_stream_info(),
711 InitState::NeedMoreInput => {
712 self.ensure_input_over()?;
713 }
714 InitState::Continue => {}
715 InitState::EndOfStream => {
716 return Err(Error::DecoderError(libxaac_sys::IA_FATAL_ERROR as i32));
717 }
718 }
719 }
720 }
721
722 pub fn decode(&mut self, input: &[u8]) -> Result<DecodedFrame> {
723 match self.decode_stream_chunk(input)? {
724 DecodeStatus::Frame(frame) => Ok(frame),
725 DecodeStatus::NeedMoreInput(_) => Err(Error::NeedMoreInput),
726 DecodeStatus::EndOfStream => Err(Error::EndOfStream),
727 }
728 }
729
730 pub fn decode_stream_chunk(&mut self, input: &[u8]) -> Result<DecodeStatus> {
731 if self.finished {
732 return Ok(DecodeStatus::EndOfStream);
733 }
734 self.pending_input.extend_from_slice(input);
735 self.drive(false)
736 }
737
738 pub fn finish(&mut self) -> Result<DecodeStatus> {
739 if self.finished {
740 return Ok(DecodeStatus::EndOfStream);
741 }
742 self.drive(true)
743 }
744
745 pub fn signal_end_of_input(&mut self) -> Result<()> {
746 self.ensure_input_over()
747 }
748
749 fn drive(&mut self, finalize: bool) -> Result<DecodeStatus> {
750 loop {
751 if !self.initialized {
752 match self.drive_initialization(finalize)? {
753 InitState::Ready => {}
754 InitState::NeedMoreInput => {
755 return Ok(DecodeStatus::NeedMoreInput(self.progress()));
756 }
757 InitState::Continue => continue,
758 InitState::EndOfStream => {
759 self.finished = true;
760 return Ok(DecodeStatus::EndOfStream);
761 }
762 }
763 }
764
765 match self.execute_once(finalize)? {
766 ExecuteState::Frame(frame) => return Ok(DecodeStatus::Frame(frame)),
767 ExecuteState::NeedMoreInput => {
768 return Ok(DecodeStatus::NeedMoreInput(self.progress()));
769 }
770 ExecuteState::Continue => continue,
771 ExecuteState::EndOfStream => {
772 self.finished = true;
773 return Ok(DecodeStatus::EndOfStream);
774 }
775 }
776 }
777 }
778
779 fn drive_initialization(&mut self, finalize: bool) -> Result<InitState> {
780 if !finalize && self.pending_input.len() < DECODER_MIN_INIT_BYTES {
781 return Ok(InitState::NeedMoreInput);
782 }
783 if self.pending_input.is_empty() && finalize {
784 self.ensure_input_over()?;
785 }
786 if self.pending_input.is_empty() && self.input_over_signaled {
787 return Ok(InitState::EndOfStream);
788 }
789
790 let bytes = self.load_input_window();
791 if bytes == 0 {
792 return Ok(InitState::NeedMoreInput);
793 }
794
795 let mut bytes_i32 = bytes as i32;
796 check_decoder(self.call_with_value(
797 libxaac_sys::IA_API_CMD_SET_INPUT_BYTES as i32,
798 0,
799 (&mut bytes_i32 as *mut _) as *mut c_void,
800 ))?;
801 let status = self.call(
802 libxaac_sys::IA_API_CMD_INIT as i32,
803 libxaac_sys::IA_CMD_TYPE_INIT_PROCESS as i32,
804 ptr::null_mut(),
805 );
806 if is_fatal(status) {
807 return Err(Error::DecoderError(status));
808 }
809
810 let consumed = self.query_consumed()? as usize;
811 self.consume_pending(consumed)?;
812
813 let mut init_done = 0i32;
814 check_decoder(self.call_with_value(
815 libxaac_sys::IA_API_CMD_INIT as i32,
816 libxaac_sys::IA_CMD_TYPE_INIT_DONE_QUERY as i32,
817 (&mut init_done as *mut _) as *mut c_void,
818 ))?;
819
820 if init_done != 0 {
821 self.initialized = true;
822 let info = self.refresh_stream_info()?;
823 self.try_initialize_drc(&info)?;
824 return Ok(InitState::Ready);
825 }
826
827 if !finalize && consumed == 0 && bytes < self.input_capacity {
828 return Ok(InitState::NeedMoreInput);
829 }
830
831 if self.pending_input.is_empty() && finalize {
832 self.ensure_input_over()?;
833 if self.pending_input.is_empty() && self.input_over_signaled {
834 return Ok(InitState::NeedMoreInput);
835 }
836 }
837
838 if self.pending_input.is_empty() {
839 Ok(InitState::NeedMoreInput)
840 } else {
841 Ok(InitState::Continue)
842 }
843 }
844
845 fn execute_once(&mut self, finalize: bool) -> Result<ExecuteState> {
846 if self.pending_input.is_empty() && finalize {
847 self.ensure_input_over()?;
848 }
849 if self.pending_input.is_empty() && self.input_over_signaled {
850 return Ok(ExecuteState::EndOfStream);
851 }
852
853 let bytes = self.load_input_window();
854 let mut bytes_i32 = bytes as i32;
855 check_decoder(self.call_with_value(
856 libxaac_sys::IA_API_CMD_SET_INPUT_BYTES as i32,
857 0,
858 (&mut bytes_i32 as *mut _) as *mut c_void,
859 ))?;
860 let status = self.call(
861 libxaac_sys::IA_API_CMD_EXECUTE as i32,
862 libxaac_sys::IA_CMD_TYPE_DO_EXECUTE as i32,
863 ptr::null_mut(),
864 );
865 if is_fatal(status) {
866 return Err(Error::DecoderError(status));
867 }
868
869 let consumed = self.query_consumed()? as usize;
870 self.consume_pending(consumed)?;
871
872 let mut done = 0i32;
873 check_decoder(self.call_with_value(
874 libxaac_sys::IA_API_CMD_EXECUTE as i32,
875 libxaac_sys::IA_CMD_TYPE_DONE_QUERY as i32,
876 (&mut done as *mut _) as *mut c_void,
877 ))?;
878
879 let mut out_bytes = 0i32;
880 check_decoder(self.call_with_value(
881 libxaac_sys::IA_API_CMD_GET_OUTPUT_BYTES as i32,
882 0,
883 (&mut out_bytes as *mut _) as *mut c_void,
884 ))?;
885
886 let info = self.refresh_stream_info()?;
887 let mut pcm = self.read_output_bytes(out_bytes.max(0) as usize)?;
888 if !pcm.is_empty() {
889 let gain_payload = if info.drc_active {
890 self.read_optional_buffer(
891 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF as i32,
892 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN as i32,
893 )?
894 } else {
895 None
896 };
897 if let Some(drc) = self.drc_decoder.as_mut().filter(|_| info.drc_active) {
898 pcm = drc.process_pcm(&pcm, &info, gain_payload.as_deref())?;
899 }
900 return Ok(ExecuteState::Frame(DecodedFrame {
901 pcm,
902 bytes_consumed: consumed,
903 stream_info: info,
904 }));
905 }
906
907 if !finalize && consumed == 0 && bytes < self.input_capacity && done == 0 {
908 return Ok(ExecuteState::NeedMoreInput);
909 }
910
911 if done != 0 && self.pending_input.is_empty() && self.input_over_signaled {
912 return Ok(ExecuteState::EndOfStream);
913 }
914 if self.pending_input.is_empty() && !finalize && !self.input_over_signaled {
915 return Ok(ExecuteState::NeedMoreInput);
916 }
917 if self.pending_input.is_empty() && finalize && self.input_over_signaled {
918 return Ok(ExecuteState::EndOfStream);
919 }
920 Ok(ExecuteState::Continue)
921 }
922
923 fn apply_config(&mut self) -> Result<()> {
924 self.set_config(
925 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ as i32,
926 self.config.pcm_word_size as i32,
927 )?;
928 self.set_config(
929 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DOWNMIX as i32,
930 i32::from(self.config.downmix_to_mono),
931 )?;
932 self.set_config(
933 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_TOSTEREO as i32,
934 i32::from(self.config.to_stereo),
935 )?;
936 self.set_config(
937 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DSAMPLE as i32,
938 i32::from(self.config.downsample_sbr),
939 )?;
940 self.set_config(
941 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4 as i32,
942 i32::from(matches!(self.config.transport, DecoderTransport::Mp4Raw)),
943 )?;
944 self.set_config(
945 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_MAX_CHANNEL as i32,
946 i32::from(self.config.max_channels),
947 )?;
948 self.set_config(
949 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_COUP_CHANNEL as i32,
950 i32::from(self.config.coupling_channels),
951 )?;
952 self.set_config(
953 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DOWNMIX_STEREO as i32,
954 i32::from(self.config.downmix_to_stereo),
955 )?;
956 self.set_config(
957 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_DISABLE_SYNC as i32,
958 i32::from(
959 self.config.disable_sync
960 || matches!(
961 self.config.transport,
962 DecoderTransport::Raw | DecoderTransport::Mp4Raw
963 ),
964 ),
965 )?;
966 self.set_config(
967 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_AUTO_SBR_UPSAMPLE as i32,
968 i32::from(self.config.auto_sbr_upsample),
969 )?;
970 self.set_config_f32(
971 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT as i32,
972 self.config.drc.cut,
973 )?;
974 self.set_config_f32(
975 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST as i32,
976 self.config.drc.boost,
977 )?;
978 self.set_config(
979 libxaac_sys::IA_XHEAAC_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL as i32,
980 i32::from(self.config.drc.target_level),
981 )?;
982 self.set_config(
983 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP as i32,
984 i32::from(self.config.drc.heavy_compression),
985 )?;
986 self.set_config(
987 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE as i32,
988 self.config.drc.effect_type.raw(),
989 )?;
990 if let Some(target_loudness) = self.config.drc.target_loudness {
991 self.set_config(
992 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS as i32,
993 target_loudness,
994 )?;
995 }
996 if let Some(leveling) = self.config.drc.loudness_leveling {
997 let _ = self.set_config_optional(
998 IA_XHEAAC_DEC_CONFIG_PARAM_DRC_LOUDNESS_LEVELING,
999 i32::from(leveling),
1000 );
1001 }
1002 self.set_config(
1003 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_FRAMESIZE as i32,
1004 i32::from(self.config.ld_frame_480),
1005 )?;
1006 self.set_config(
1007 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_HQ_ESBR as i32,
1008 i32::from(self.config.hq_esbr),
1009 )?;
1010 self.set_config(
1011 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_PS_ENABLE as i32,
1012 i32::from(self.config.ps_enable),
1013 )?;
1014 self.set_config(
1015 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_PEAK_LIMITER as i32,
1016 i32::from(!self.config.peak_limiter),
1017 )?;
1018 self.set_config(
1019 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_FRAMELENGTH_FLAG as i32,
1020 i32::from(self.config.frame_length_960),
1021 )?;
1022 self.set_config(
1023 libxaac_sys::IA_XHEAAC_DEC_CONFIG_ERROR_CONCEALMENT as i32,
1024 i32::from(self.config.error_concealment),
1025 )?;
1026 self.set_config(
1027 libxaac_sys::IA_XHEAAC_DEC_CONFIG_PARAM_ESBR as i32,
1028 i32::from(self.config.enable_esbr),
1029 )?;
1030
1031 if let Some(raw) = self.config.raw {
1032 self.set_config(
1033 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_SAMP_FREQ as i32,
1034 raw.sample_rate as i32,
1035 )?;
1036 self.set_config(
1037 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_AOT as i32,
1038 raw.audio_object_type.aot(),
1039 )?;
1040 }
1041 Ok(())
1042 }
1043
1044 fn allocate_memory(&mut self) -> Result<()> {
1045 let mut memtabs_size = 0u32;
1046 check_decoder(self.call_with_value(
1047 libxaac_sys::IA_API_CMD_GET_MEMTABS_SIZE as i32,
1048 0,
1049 (&mut memtabs_size as *mut _) as *mut c_void,
1050 ))?;
1051 self.memtabs = AlignedBuffer::new(memtabs_size as usize, 4)?;
1052 check_decoder(self.call_with_value(
1053 libxaac_sys::IA_API_CMD_SET_MEMTABS_PTR as i32,
1054 0,
1055 self.memtabs.as_ptr().cast::<c_void>(),
1056 ))?;
1057
1058 check_decoder(self.call(
1059 libxaac_sys::IA_API_CMD_INIT as i32,
1060 libxaac_sys::IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS as i32,
1061 ptr::null_mut(),
1062 ))?;
1063
1064 let mut mem_count = 0i32;
1065 check_decoder(self.call_with_value(
1066 libxaac_sys::IA_API_CMD_GET_N_MEMTABS as i32,
1067 0,
1068 (&mut mem_count as *mut _) as *mut c_void,
1069 ))?;
1070
1071 for index in 0..mem_count {
1072 let mut size = 0u32;
1073 let mut alignment = 0u32;
1074 let mut mem_type = 0u32;
1075
1076 check_decoder(self.call_with_value(
1077 libxaac_sys::IA_API_CMD_GET_MEM_INFO_SIZE as i32,
1078 index,
1079 (&mut size as *mut _) as *mut c_void,
1080 ))?;
1081 check_decoder(self.call_with_value(
1082 libxaac_sys::IA_API_CMD_GET_MEM_INFO_ALIGNMENT as i32,
1083 index,
1084 (&mut alignment as *mut _) as *mut c_void,
1085 ))?;
1086 check_decoder(self.call_with_value(
1087 libxaac_sys::IA_API_CMD_GET_MEM_INFO_TYPE as i32,
1088 index,
1089 (&mut mem_type as *mut _) as *mut c_void,
1090 ))?;
1091
1092 let block = AlignedBuffer::new(size as usize, alignment.max(1) as usize)?;
1093 let ptr = block.as_ptr().cast::<c_void>();
1094 check_decoder(self.call_with_value(
1095 libxaac_sys::IA_API_CMD_SET_MEM_PTR as i32,
1096 index,
1097 ptr,
1098 ))?;
1099
1100 if mem_type == libxaac_sys::IA_MEMTYPE_INPUT {
1101 self.input_index = self.memblocks.len();
1102 self.input_capacity = size as usize;
1103 } else if mem_type == libxaac_sys::IA_MEMTYPE_OUTPUT {
1104 self.output_index = self.memblocks.len();
1105 }
1106
1107 self.memblocks.push(block);
1108 }
1109
1110 Ok(())
1111 }
1112
1113 fn try_initialize_drc(&mut self, info: &StreamInfo) -> Result<()> {
1114 if !self.config.drc.enabled || self.drc_decoder.is_some() {
1115 return Ok(());
1116 }
1117 if info.extension_elements.unwrap_or(0) == 0
1118 && info.config_extensions.unwrap_or(0) == 0
1119 && info.gain_payload_len.unwrap_or(0) == 0
1120 {
1121 return Ok(());
1122 }
1123
1124 let mut drc = DrcDecoder::new(info)?;
1125 if let Some(payloads) = self.read_extension_payloads()? {
1126 for payload in &payloads.loudness_payloads {
1127 drc.copy_split_payload(0x000D, IA_CMD_TYPE_INIT_CPY_IL_BSF_BUFF, payload, 1)?;
1128 }
1129 for payload in &payloads.config_payloads {
1130 drc.copy_split_payload(0x000C, IA_CMD_TYPE_INIT_CPY_IC_BSF_BUFF, payload, 1)?;
1131 }
1132 if !payloads.has_any() {
1133 self.drc_decoder = Some(drc);
1134 return Ok(());
1135 }
1136 let interface_present = 1i32;
1137 drc.set_config(IA_DRC_DEC_CONFIG_PARAM_INT_PRESENT, interface_present)?;
1138 check_decoder(drc.call(
1139 libxaac_sys::IA_API_CMD_INIT as i32,
1140 IA_CMD_TYPE_INIT_CPY_IN_BSF_BUFF,
1141 ptr::null_mut(),
1142 ))?;
1143 check_decoder(drc.call(
1144 libxaac_sys::IA_API_CMD_INIT as i32,
1145 libxaac_sys::IA_CMD_TYPE_INIT_PROCESS as i32,
1146 ptr::null_mut(),
1147 ))?;
1148 }
1149 self.drc_decoder = Some(drc);
1150 if let Some(cached) = self.cached_info.as_mut() {
1151 cached.drc_active = true;
1152 }
1153 Ok(())
1154 }
1155
1156 fn refresh_stream_info(&mut self) -> Result<StreamInfo> {
1157 let sample_rate =
1158 self.get_config_required(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_SAMP_FREQ as i32)?;
1159 let channels = self
1160 .get_config_required(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS as i32)?;
1161 let channel_mask = self
1162 .get_config_required(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MASK as i32)?;
1163 let sbr_mode =
1164 self.get_config_required(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE as i32)?;
1165 let aot =
1166 self.get_config_required(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_AOT as i32)?;
1167
1168 let info = StreamInfo {
1169 sample_rate: sample_rate.max(0) as u32,
1170 channels: channels.max(0) as u16,
1171 channel_mask: channel_mask.max(0) as u32,
1172 channel_mode: self
1173 .get_config_optional(
1174 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MODE as i32,
1175 )?
1176 .map(ChannelMode::from),
1177 pcm_word_size: self.config.pcm_word_size,
1178 sbr_mode: SbrMode::from(sbr_mode),
1179 audio_object_type: aot,
1180 drc_effect_type: self
1181 .get_config_optional(
1182 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE as i32,
1183 )?
1184 .map(DrcEffectType::from_raw),
1185 drc_target_loudness: self.get_config_optional(
1186 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS as i32,
1187 )?,
1188 drc_loudness_norm: self.get_config_optional(
1189 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM as i32,
1190 )?,
1191 loudness_leveling: self
1192 .get_config_optional(IA_XHEAAC_DEC_CONFIG_PARAM_DRC_LOUDNESS_LEVELING)?
1193 .map(|value| value != 0),
1194 preroll_frames: self
1195 .get_config_optional(
1196 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_GET_NUM_PRE_ROLL_FRAMES as i32,
1197 )?
1198 .map(|value| value.max(0) as u32),
1199 drc_config_changed: self
1200 .get_config_optional(libxaac_sys::IA_ENHAACPLUS_DEC_DRC_IS_CONFIG_CHANGED as i32)?
1201 .map(|value| value != 0),
1202 drc_apply_crossfade: self
1203 .get_config_optional(libxaac_sys::IA_ENHAACPLUS_DEC_DRC_APPLY_CROSSFADE as i32)?
1204 .map(|value| value != 0),
1205 extension_elements: self
1206 .get_config_optional(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_NUM_ELE as i32)?
1207 .map(|value| value.max(0) as u32),
1208 config_extensions: self
1209 .get_config_optional(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_NUM_CONFIG_EXT as i32)?
1210 .map(|value| value.max(0) as u32),
1211 gain_payload_len: self
1212 .get_config_optional(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN as i32)?
1213 .map(|value| value.max(0) as u32),
1214 drc_active: self.drc_decoder.is_some(),
1215 };
1216 self.cached_info = Some(info.clone());
1217 Ok(info)
1218 }
1219
1220 fn read_extension_payloads(&self) -> Result<Option<ExtensionPayloads>> {
1221 let num_elements = self
1222 .get_config_optional(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_NUM_ELE as i32)?
1223 .unwrap_or_default()
1224 .max(0) as usize;
1225 let num_config_ext = self
1226 .get_config_optional(libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_NUM_CONFIG_EXT as i32)?
1227 .unwrap_or_default()
1228 .max(0) as usize;
1229 if num_elements == 0 && num_config_ext == 0 {
1230 return Ok(None);
1231 }
1232
1233 let mut sizes = [[0i32; 16]; 2];
1234 check_decoder(self.get_config_raw(
1235 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_BUF_SIZES as i32,
1236 sizes.as_mut_ptr().cast::<c_void>(),
1237 ))?;
1238 let mut ptrs = [[ptr::null_mut::<u8>(); 16]; 2];
1239 check_decoder(self.get_config_raw(
1240 libxaac_sys::IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_PTR as i32,
1241 ptrs.as_mut_ptr().cast::<c_void>(),
1242 ))?;
1243
1244 let mut payloads = ExtensionPayloads::default();
1245 for index in 0..num_config_ext.min(16) {
1246 let size = sizes[0][index].max(0) as usize;
1247 if size == 0 || ptrs[0][index].is_null() {
1248 continue;
1249 }
1250 payloads.loudness_payloads.push(unsafe {
1251 std::slice::from_raw_parts(ptrs[0][index].cast::<u8>(), size).to_vec()
1252 });
1253 }
1254 for index in 0..num_elements.min(16) {
1255 let size = sizes[1][index].max(0) as usize;
1256 if size == 0 || ptrs[1][index].is_null() {
1257 continue;
1258 }
1259 payloads.config_payloads.push(unsafe {
1260 std::slice::from_raw_parts(ptrs[1][index].cast::<u8>(), size).to_vec()
1261 });
1262 }
1263 Ok(Some(payloads))
1264 }
1265
1266 fn read_optional_buffer(&self, ptr_index: i32, len_index: i32) -> Result<Option<Vec<u8>>> {
1267 let len = match self.get_config_optional(len_index)? {
1268 Some(len) if len > 0 => len as usize,
1269 _ => return Ok(None),
1270 };
1271 let mut ptr_value: *mut u8 = ptr::null_mut();
1272 check_decoder(self.get_config_raw(ptr_index, (&mut ptr_value as *mut _) as *mut c_void))?;
1273 if ptr_value.is_null() {
1274 return Ok(None);
1275 }
1276 Ok(Some(unsafe {
1277 std::slice::from_raw_parts(ptr_value.cast::<u8>(), len).to_vec()
1278 }))
1279 }
1280
1281 fn progress(&self) -> DecodeProgress {
1282 DecodeProgress {
1283 initialized: self.initialized,
1284 stream_info: self.cached_info.clone(),
1285 }
1286 }
1287
1288 fn load_input_window(&mut self) -> usize {
1289 let len = self.pending_input.len().min(self.input_capacity);
1290 let input_ptr = self.memblocks[self.input_index].as_ptr();
1291 unsafe {
1292 if len != 0 {
1293 ptr::copy_nonoverlapping(self.pending_input.as_ptr(), input_ptr, len);
1294 }
1295 if len < self.input_capacity {
1296 ptr::write_bytes(input_ptr.add(len), 0, self.input_capacity - len);
1297 }
1298 }
1299 len
1300 }
1301
1302 fn read_output_bytes(&self, len: usize) -> Result<Vec<u8>> {
1303 let out_ptr = self.memblocks[self.output_index].as_ptr();
1304 if out_ptr.is_null() {
1305 return Err(Error::InvalidConfig("decoder output buffer missing"));
1306 }
1307 Ok(unsafe { std::slice::from_raw_parts(out_ptr, len) }.to_vec())
1308 }
1309
1310 fn consume_pending(&mut self, consumed: usize) -> Result<()> {
1311 if consumed > self.pending_input.len() {
1312 return Err(Error::DecoderError(libxaac_sys::IA_FATAL_ERROR as i32));
1313 }
1314 self.pending_input.drain(..consumed);
1315 Ok(())
1316 }
1317
1318 fn ensure_input_over(&mut self) -> Result<()> {
1319 if self.input_over_signaled {
1320 return Ok(());
1321 }
1322 check_decoder(self.call(
1323 libxaac_sys::IA_API_CMD_INPUT_OVER as i32,
1324 0,
1325 ptr::null_mut(),
1326 ))?;
1327 self.input_over_signaled = true;
1328 Ok(())
1329 }
1330
1331 fn query_consumed(&self) -> Result<i32> {
1332 let mut consumed = 0i32;
1333 check_decoder(self.call_with_value(
1334 libxaac_sys::IA_API_CMD_GET_CURIDX_INPUT_BUF as i32,
1335 0,
1336 (&mut consumed as *mut _) as *mut c_void,
1337 ))?;
1338 Ok(consumed.max(0))
1339 }
1340
1341 fn set_config(&mut self, index: i32, value: i32) -> Result<()> {
1342 let mut value = value;
1343 check_decoder(self.call_with_value(
1344 libxaac_sys::IA_API_CMD_SET_CONFIG_PARAM as i32,
1345 index,
1346 (&mut value as *mut _) as *mut c_void,
1347 ))
1348 }
1349
1350 fn set_config_optional(&mut self, index: i32, value: i32) -> Result<()> {
1351 let mut value = value;
1352 let status = self.call_with_value(
1353 libxaac_sys::IA_API_CMD_SET_CONFIG_PARAM as i32,
1354 index,
1355 (&mut value as *mut _) as *mut c_void,
1356 );
1357 if status == libxaac_sys::IA_NO_ERROR as i32 || !is_fatal(status) {
1358 Ok(())
1359 } else {
1360 Err(Error::DecoderError(status))
1361 }
1362 }
1363
1364 fn set_config_f32(&mut self, index: i32, value: f32) -> Result<()> {
1365 let mut value = value;
1366 check_decoder(self.call_with_value(
1367 libxaac_sys::IA_API_CMD_SET_CONFIG_PARAM as i32,
1368 index,
1369 (&mut value as *mut _) as *mut c_void,
1370 ))
1371 }
1372
1373 fn get_config_required(&self, index: i32) -> Result<i32> {
1374 self.get_config_optional(index)?
1375 .ok_or(Error::DecoderError(libxaac_sys::IA_FATAL_ERROR as i32))
1376 }
1377
1378 fn get_config_optional(&self, index: i32) -> Result<Option<i32>> {
1379 let mut value = 0i32;
1380 let status = self.get_config(index, &mut value);
1381 if status == libxaac_sys::IA_NO_ERROR as i32 {
1382 Ok(Some(value))
1383 } else if is_fatal(status) {
1384 Err(Error::DecoderError(status))
1385 } else {
1386 Ok(None)
1387 }
1388 }
1389
1390 fn get_config_raw(&self, index: i32, value: *mut c_void) -> i32 {
1391 unsafe {
1392 libxaac_sys::ixheaacd_dec_api(
1393 self.api.as_ptr().cast::<c_void>(),
1394 libxaac_sys::IA_API_CMD_GET_CONFIG_PARAM as i32,
1395 index,
1396 value,
1397 )
1398 }
1399 }
1400
1401 fn get_config(&self, index: i32, value: &mut i32) -> i32 {
1402 self.get_config_raw(index, (value as *mut _) as *mut c_void)
1403 }
1404
1405 fn call(&self, cmd: i32, idx: i32, value: *mut c_void) -> i32 {
1406 unsafe {
1407 libxaac_sys::ixheaacd_dec_api(self.api.as_ptr().cast::<c_void>(), cmd, idx, value)
1408 }
1409 }
1410
1411 fn call_with_value(&self, cmd: i32, idx: i32, value: *mut c_void) -> i32 {
1412 self.call(cmd, idx, value)
1413 }
1414}
1415
1416#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1417enum InitState {
1418 Ready,
1419 NeedMoreInput,
1420 Continue,
1421 EndOfStream,
1422}
1423
1424#[derive(Debug, Clone, PartialEq, Eq)]
1425enum ExecuteState {
1426 Frame(DecodedFrame),
1427 NeedMoreInput,
1428 Continue,
1429 EndOfStream,
1430}
1431
1432#[derive(Debug, Default)]
1433struct ExtensionPayloads {
1434 loudness_payloads: Vec<Vec<u8>>,
1435 config_payloads: Vec<Vec<u8>>,
1436}
1437
1438impl ExtensionPayloads {
1439 fn has_any(&self) -> bool {
1440 !self.loudness_payloads.is_empty() || !self.config_payloads.is_empty()
1441 }
1442}
1443
1444impl DrcEffectType {
1445 fn from_raw(value: i32) -> Self {
1446 match value {
1447 1 => Self::Night,
1448 2 => Self::Noisy,
1449 3 => Self::Limited,
1450 4 => Self::LowLevel,
1451 5 => Self::Dialog,
1452 6 => Self::GeneralCompression,
1453 7 => Self::Expanded,
1454 8 => Self::Articulated,
1455 9 => Self::Headphone,
1456 10 => Self::PortableSpeaker,
1457 11 => Self::StereoDownmix,
1458 _ => Self::None,
1459 }
1460 }
1461}
1462
1463fn is_fatal(status: i32) -> bool {
1464 (status as u32 & libxaac_sys::IA_FATAL_ERROR) != 0
1465}