From 63c8cb6ec9ec5d1fb954a37f53dbc532bb762ba8 Mon Sep 17 00:00:00 2001 From: Rumaan Khan <100922@ittiam.com> Date: Thu, 26 Jun 2025 17:55:06 +0530 Subject: [PATCH 1/3] mp4 supp changes --- test/decoder/ixheaacd_main.c | 455 +++++++++++++++++++++++++++++++++-- test/decoder/xaacdec.cmake | 27 ++- 2 files changed, 465 insertions(+), 17 deletions(-) diff --git a/test/decoder/ixheaacd_main.c b/test/decoder/ixheaacd_main.c index b7e6c8c..a96cf0e 100644 --- a/test/decoder/ixheaacd_main.c +++ b/test/decoder/ixheaacd_main.c @@ -33,6 +33,16 @@ #include "ixheaacd_metadata_read.h" #include "impd_drc_config_params.h" +#ifdef SUPPORT_MP4 +#include "ISOMovies.h" +#define _IA_HANDLE_ERROR_MP4(a) \ +if (a) \ +{ \ + printf("ISOBMFF parser library error. Error No: %d\n", a); \ + exit(1); \ +} +#endif + IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_module_obj, WORD32 i_cmd, WORD32 i_idx, pVOID pv_value); @@ -100,13 +110,23 @@ FileWrapperPtr g_pf_inp; /* file pointer to bitstream file (mp4) */ WORD32 mpeg_d_drc_on = 0; +#ifndef SUPPORT_MP4 metadata_info meta_info; // metadata pointer; WORD32 ixheaacd_i_bytes_to_read; -WORD32 prev_i_bytes_to_read; -WORD32 flush_frame = 0; FILE *g_pf_meta; WORD32 raw_testing = 0; +#else +WORD32 mp4_flag = 0; +WORD32 ixheaacd_i_bytes_to_read; +ISOMedia media; +ISOTrack trak; +ISOTrackReader reader; +ISOHandle sample_hdl; +ISOHandle decoder_cfg_hdl; +#endif +WORD32 prev_i_bytes_to_read; +WORD32 flush_frame = 0; WORD32 eld_testing = 0; WORD32 ec_enable = 0; WORD32 esbr_testing = 1; @@ -387,6 +407,7 @@ IA_ERRORCODE ixheaacd_set_config_param(WORD32 argc, pWORD8 argv[], ia_error_info_struct *p_proc_err_info = &ixheaacd_error_info; for (i = 0; i < argc; i++) { +#ifndef SUPPORT_MP4 /* To indicate if its a MP4 file or not. */ if (!strncmp((pCHAR8)argv[i], "-mp4:", 5)) { pCHAR8 pb_arg_val = (pCHAR8)(argv[i] + 5); @@ -396,6 +417,7 @@ IA_ERRORCODE ixheaacd_set_config_param(WORD32 argc, pWORD8 argv[], IA_XHEAAC_DEC_CONFIG_PARAM_MP4FLAG, &ui_mp4_flag); _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); } +#endif /* PCM WORD Size (For single input file) */ if (!strncmp((pCHAR8)argv[i], "-pcmsz:", 7)) { pCHAR8 pb_arg_val = (pCHAR8)(argv[i] + 7); @@ -668,6 +690,15 @@ IA_ERRORCODE ixheaacd_set_config_param(WORD32 argc, pWORD8 argv[], ec_enable = ui_err_conceal; } } +#ifdef SUPPORT_MP4 + { + UWORD32 ui_mp4_flag = mp4_flag; + err_code = (*p_ia_process_api)( + p_ia_process_api_obj, IA_API_CMD_SET_CONFIG_PARAM, + IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4, &ui_mp4_flag); + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + } +#endif return IA_NO_ERROR; } @@ -872,6 +903,11 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { WORD32 prev_sampling_rate = 0; WORD32 skip_samples = 0; WORD32 total_samples = 0; +#ifdef SUPPORT_MP4 + s64 segment_duration = 0; + s64 start_offset_duration = 0; + u32 entryIndex = 1; +#endif WORD32 write_flag = 1; WORD32 bytes_to_write = 0; WORD32 ixheaacd_drc_offset = 0; @@ -920,6 +956,10 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { /* The process error info structure */ ia_error_info_struct *p_proc_err_info; +#ifdef SUPPORT_MP4 + ISOErr err = ISONoErr; +#endif + /* Process struct initing */ p_ia_process_api = ixheaacd_dec_api; p_set_config_param = ixheaacd_set_config_param; @@ -1197,6 +1237,7 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { do { i_bytes_read = 0; +#ifndef SUPPORT_MP4 if ((ui_inp_size - (i_buff_size - i_bytes_consumed)) > 0) { for (i = 0; i < (i_buff_size - i_bytes_consumed); i++) { pb_inp_buf[i] = pb_inp_buf[i + i_bytes_consumed]; @@ -1259,8 +1300,72 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { #endif return 1; } +#else + if (!mp4_flag) + { + if ((ui_inp_size - (i_buff_size - i_bytes_consumed)) > 0) { + for (i = 0; i < (i_buff_size - i_bytes_consumed); i++) { + pb_inp_buf[i] = pb_inp_buf[i + i_bytes_consumed]; + } + FileWrapper_Read(g_pf_inp, (unsigned char *)(pb_inp_buf + i_buff_size - + i_bytes_consumed), + (ui_inp_size - (i_buff_size - i_bytes_consumed)), + (pUWORD32)&i_bytes_read); + + i_buff_size = i_buff_size - (i_bytes_consumed - i_bytes_read); + + /* Tell input is over, if algorithm returns with insufficient input and + there is no + more input left in the bitstream*/ + if ((i_buff_size <= 0) || + ((err_code_reinit == 0x00001804) && i_bytes_read == 0)) + { + i_buff_size = 0; + /* Tell that the input is over in this buffer */ + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, + IA_API_CMD_INPUT_OVER, 0, NULL); + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + } + } + + if ((i_buff_size <= 0) || + ((err_code_reinit == 0x00001804) && i_bytes_read == 0)) { + i_buff_size = 0; + /* Tell that the input is over in this buffer */ + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, + IA_API_CMD_INPUT_OVER, 0, NULL); + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); +#ifdef WAV_HEADER +#ifndef ARM_PROFILE_BOARD + /* ******************************************************************/ + /* Get config params from API */ + /* ******************************************************************/ + + err_code = + (*p_get_config_param)(pv_ia_process_api_obj, &i_samp_freq, + &i_num_chan, &i_pcm_wd_sz, &i_channel_mask, + &i_sbr_mode, &ui_aot); + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + + // This is done in those cases, where file decodes ends at init time + // Since init is incomplete, sampling freq might be zero and will result + // in + // writing invalid wave header + + if (i_samp_freq == 0) i_samp_freq = prev_sampling_rate; + + if (!fseek(g_pf_out, 0, SEEK_SET)) + write_wav_header(g_pf_out, i_total_bytes, i_samp_freq, i_num_chan, + i_pcm_wd_sz, i_channel_mask); +#endif +#endif + return 1; + } + } +#endif if (init_iteration == 1) { +#ifndef SUPPORT_MP4 if (raw_testing) ixheaacd_i_bytes_to_read = get_metadata_dec_info_init(meta_info); else @@ -1271,8 +1376,52 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, 0, &ixheaacd_i_bytes_to_read); init_iteration++; +#else + if (!mp4_flag) + { + ixheaacd_i_bytes_to_read = i_buff_size; + /* Set number of bytes to be processed */ + err_code = + (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, + 0, &ixheaacd_i_bytes_to_read); + } + else + { + u32 samp_desc_idx = 1, obj_type = 0, output_size; + u32 avg_br = 0, max_br = 0, strm_type = 0, strm_up = 0; + err = MP4GetMediaDecoderInformation(media, + samp_desc_idx, + &obj_type, + &strm_type, + &output_size, + &strm_up, + &max_br, + &avg_br, + decoder_cfg_hdl); + _IA_HANDLE_ERROR_MP4(err); + err = MP4GetHandleSize(decoder_cfg_hdl, &ixheaacd_i_bytes_to_read); + _IA_HANDLE_ERROR_MP4(err); + if (ixheaacd_i_bytes_to_read > (WORD32)ui_inp_size) + return IA_FATAL_ERROR; + /* Set number of bytes to be processed */ + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, + IA_API_CMD_SET_INPUT_BYTES, 0, + &ixheaacd_i_bytes_to_read); + memcpy(pb_inp_buf, *decoder_cfg_hdl, ixheaacd_i_bytes_to_read); + if (ixheaacd_i_bytes_to_read <= 0) { + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, + IA_API_CMD_INPUT_OVER, 0, NULL); + + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + + return IA_NO_ERROR; + } + } + init_iteration++; +#endif } else { +#ifndef SUPPORT_MP4 if (raw_testing) { ixheaacd_i_bytes_to_read = get_metadata_dec_exec(meta_info, frame_counter); @@ -1299,6 +1448,44 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { err_code = (*p_ia_process_api)( pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, 0, &i_buff_size); } +#else + if (mp4_flag) { + u32 unit_size; + s32 cts; + s32 dts; + u32 sample_flags; + err = MP4TrackReaderGetNextAccessUnit( + reader, sample_hdl, &unit_size, &sample_flags, &cts, &dts); + if (err) + { + if (err == ISOEOF) err = ISONoErr; + break; + } + ixheaacd_i_bytes_to_read = unit_size; + i_bytes_read = ixheaacd_i_bytes_to_read; + if (ixheaacd_i_bytes_to_read > (WORD32)ui_inp_size) + return IA_FATAL_ERROR; + + if (ixheaacd_i_bytes_to_read <= 0) { + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, + IA_API_CMD_INPUT_OVER, 0, NULL); + + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + return IA_NO_ERROR; + } + + /* Set number of bytes to be processed */ + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, + IA_API_CMD_SET_INPUT_BYTES, 0, + &ixheaacd_i_bytes_to_read); + memcpy(pb_inp_buf, *((char **)sample_hdl), ixheaacd_i_bytes_to_read); + init_iteration++; + } else { + /* Set number of bytes to be processed */ + err_code = (*p_ia_process_api)( + pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, 0, &i_buff_size); + } +#endif } _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); @@ -1646,6 +1833,7 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { if (ui_aot == 42) esbr_testing = 1; +#ifndef SUPPORT_MP4 if (raw_testing) { skip_samples = get_start_offset_in_samples(meta_info); if (ui_aot >= 23 && esbr_testing) { @@ -1656,6 +1844,21 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { } if (eld_testing == 0) total_samples = get_play_time_in_samples(meta_info); } +#else + if (mp4_flag) { + u32 entry_count = 1; + err = ISOGetTrackEditlistEntryCount(trak, &entry_count); + if (err == MP4NoErr) + { + err = ISOGetTrackEditlist(trak, &segment_duration, &start_offset_duration, 1); + if (err == MP4NoErr) + { + skip_samples = (WORD32)start_offset_duration; + if (eld_testing == 0) total_samples = (WORD32)segment_duration; + } + } + } +#endif /* End second part */ @@ -1672,26 +1875,67 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { #endif prev_sampling_rate = i_samp_freq; +#if SUPPORT_MP4 + UWORD32 number_of_frames = 0; + err = ISOGetMediaSampleCount(media, &number_of_frames); + if (err) return err; +#else + UWORD32 number_of_frames = meta_info.ia_mp4_stsz_entries; +#endif + do { if (((WORD32)ui_inp_size - (WORD32)(i_buff_size - i_bytes_consumed)) > 0) { if (i_sbr_mode && (ui_aot < 23) && esbr_testing) { - if (meta_info.ia_mp4_stsz_entries != frame_counter) { + if (number_of_frames != frame_counter) { for (i = 0; i < (i_buff_size - i_bytes_consumed); i++) { pb_inp_buf[i] = pb_inp_buf[i + i_bytes_consumed]; } - +#ifndef SUPPORT_MP4 FileWrapper_Read( g_pf_inp, (unsigned char *)(pb_inp_buf + i_buff_size - i_bytes_consumed), ((WORD32)ui_inp_size - (WORD32)(i_buff_size - i_bytes_consumed)), (pUWORD32)&i_bytes_read); - +#else + if (!mp4_flag) + { + FileWrapper_Read( + g_pf_inp, + (unsigned char *)(pb_inp_buf + i_buff_size - i_bytes_consumed), + ((WORD32)ui_inp_size - (WORD32)(i_buff_size - i_bytes_consumed)), + (pUWORD32)&i_bytes_read); + } + else + { + if (i_bytes_consumed) + { + u32 unit_size; + s32 cts; + s32 dts; + u32 sample_flags; + err = MP4TrackReaderGetNextAccessUnit( + reader, sample_hdl, &unit_size, &sample_flags, &cts, &dts); + if (err) + { + if (err == ISOEOF) err = ISONoErr; + break; + } + i_bytes_read = unit_size; + memcpy(pb_inp_buf, *((char **)sample_hdl), i_bytes_read); + } + } +#endif + i_buff_size = i_buff_size - (i_bytes_consumed - i_bytes_read); if ((i_buff_size <= 0) || ((err_code_reinit == 0x00001804) && i_bytes_read == 0)) { i_buff_size = 0; +#ifndef SUPPORT_MP4 raw_testing = 0; +#else + mp4_flag = 0; +#endif /* Tell that the input is over in this buffer */ err_code = (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_INPUT_OVER, 0, NULL); @@ -1703,19 +1947,49 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { for (i = 0; i < (i_buff_size - i_bytes_consumed); i++) { pb_inp_buf[i] = pb_inp_buf[i + i_bytes_consumed]; } - +#ifndef SUPPORT_MP4 FileWrapper_Read(g_pf_inp, (unsigned char *)(pb_inp_buf + i_buff_size - i_bytes_consumed), ((WORD32)ui_inp_size - (WORD32)(i_buff_size - i_bytes_consumed)), (pUWORD32)&i_bytes_read); - +#else + if (!mp4_flag) + { + FileWrapper_Read(g_pf_inp, + (unsigned char *)(pb_inp_buf + i_buff_size - i_bytes_consumed), + ((WORD32)ui_inp_size - (WORD32)(i_buff_size - i_bytes_consumed)), + (pUWORD32)&i_bytes_read); + } + else + { + if (i_bytes_consumed) + { + u32 unit_size; + s32 cts; + s32 dts; + u32 sample_flags; + err = MP4TrackReaderGetNextAccessUnit( + reader, sample_hdl, &unit_size, &sample_flags, &cts, &dts); + if (err) + { + if (err == ISOEOF) err = ISONoErr; + break; + } + i_bytes_read = unit_size; + memcpy(pb_inp_buf, *((char **)sample_hdl), i_bytes_read); + } + } +#endif i_buff_size = i_buff_size - (i_bytes_consumed - i_bytes_read); if ((i_buff_size <= 0) || ((err_code_reinit == 0x00001804) && i_bytes_read == 0)) { i_buff_size = 0; +#ifndef SUPPORT_MP4 raw_testing = 0; - +#else + mp4_flag = 0; +#endif err_code = (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_INPUT_OVER, 0, NULL); @@ -1724,7 +1998,8 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { } } if (i_sbr_mode && (ui_aot < 23) && esbr_testing) { - if (meta_info.ia_mp4_stsz_entries != frame_counter) { + if (number_of_frames != frame_counter) { +#ifndef SUPPORT_MP4 if (raw_testing) { ixheaacd_i_bytes_to_read = get_metadata_dec_exec(meta_info, frame_counter); @@ -1743,11 +2018,31 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, 0, &ixheaacd_i_bytes_to_read); } else { +#else + if (mp4_flag) { + ixheaacd_i_bytes_to_read = i_bytes_read; + + if (ixheaacd_i_bytes_to_read > (WORD32)ui_inp_size) + return IA_FATAL_ERROR; + if (ixheaacd_i_bytes_to_read <= 0 && ec_enable == 0) { + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, + IA_API_CMD_INPUT_OVER, 0, NULL); + + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + + return IA_NO_ERROR; + } + err_code = + (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, + 0, &ixheaacd_i_bytes_to_read); + } else { +#endif err_code = (*p_ia_process_api)( pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, 0, &i_buff_size); } } } else { +#ifndef SUPPORT_MP4 if (raw_testing) { ixheaacd_i_bytes_to_read = get_metadata_dec_exec(meta_info, frame_counter); @@ -1778,6 +2073,37 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { &ixheaacd_i_bytes_to_read); } } else { +#else + if (mp4_flag) { + ixheaacd_i_bytes_to_read = i_bytes_read; + + if (ixheaacd_i_bytes_to_read > (WORD32)ui_inp_size) return IA_FATAL_ERROR; + + if (ixheaacd_i_bytes_to_read <= 0) { + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, + IA_API_CMD_INPUT_OVER, 0, NULL); + + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + + return IA_NO_ERROR; + } + + if (ec_enable == 1) { + if (ixheaacd_i_bytes_to_read != 0) { + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, 0, + &ixheaacd_i_bytes_to_read); + } else { + if (i_buff_size != 0) { + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, 0, + &i_buff_size); + } + } + } else { + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, 0, + &ixheaacd_i_bytes_to_read); + } + } else { +#endif /* Set number of bytes to be processed */ err_code = (*p_ia_process_api)( pv_ia_process_api_obj, IA_API_CMD_SET_INPUT_BYTES, 0, &i_buff_size); @@ -2064,7 +2390,13 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { if (total_samples != 0) // Usac stream { +#ifndef SUPPORT_MP4 if (raw_testing) { +#else + if (mp4_flag) { + WORD32 frame_size = i_out_bytes / (i_num_chan * (i_pcm_wd_sz >> 3)); + skip_samples = skip_samples % frame_size; +#endif if (i_total_bytes <= skip_samples * i_num_chan * (i_pcm_wd_sz >> 3)) { err_code = (*p_get_config_param)(pv_ia_process_api_obj, &i_samp_freq, @@ -2088,6 +2420,7 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { } } +#ifndef SUPPORT_MP4 if (raw_testing) { samples_written += current_samples; @@ -2097,6 +2430,17 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { if (i_out_bytes < 0) i_out_bytes = 0; } } +#else + if (mp4_flag) { + samples_written += current_samples; + + if (samples_written > total_samples) { + i_out_bytes = (total_samples - (samples_written - current_samples)) * + (i_num_chan * (i_pcm_wd_sz >> 3)); + if (i_out_bytes < 0) i_out_bytes = 0; + } + } +#endif } if (write_flag) { @@ -2326,10 +2670,17 @@ void print_usage() { int main(WORD32 argc, char *argv[]) { WORD32 i, err_code = IA_NO_ERROR; +#ifdef SUPPORT_MP4 + ISOErr err; + u32 handler_type; + ISOMovie moov; +#endif ia_testbench_error_handler_init(); g_pf_inp = NULL; +#ifndef SUPPORT_MP4 g_pf_meta = NULL; +#endif g_pf_out = NULL; for (i = 1; i < argc; i++) { @@ -2337,7 +2688,7 @@ int main(WORD32 argc, char *argv[]) { if (!strncmp((const char *)argv[i], "-ifile:", 7)) { pWORD8 pb_arg_val = (pWORD8)argv[i] + 7; - +#ifndef SUPPORT_MP4 g_pf_inp = FileWrapper_Open((char *)pb_arg_val); if (g_pf_inp == NULL) { err_code = IA_TESTBENCH_MFMAN_FATAL_FILE_OPEN_FAILED; @@ -2346,8 +2697,43 @@ int main(WORD32 argc, char *argv[]) { exit(1); } raw_testing = 0; +#else + err = ISOOpenMovieFile(&moov, (char *)pb_arg_val, + MP4OpenMovieNormal); + if (err != MP4NoErr) + { + mp4_flag = 0; + g_pf_inp = FileWrapper_Open((char *)pb_arg_val); + if (g_pf_inp == NULL) { + err_code = IA_TESTBENCH_MFMAN_FATAL_FILE_OPEN_FAILED; + ixheaacd_error_handler(&ixheaacd_ia_testbench_error_info, + (pWORD8) "Input File", err_code); + exit(1); + } + } + else + { + u32 tot_num_tracks = 0; + mp4_flag = 1; + err = ISOGetMovieTrackCount(moov, &tot_num_tracks); + _IA_HANDLE_ERROR_MP4(err); + err = ISOGetMovieIndTrack(moov, tot_num_tracks, &trak); + _IA_HANDLE_ERROR_MP4(err); + err = ISOGetTrackMedia(trak, &media); + _IA_HANDLE_ERROR_MP4(err); + err = ISOGetMediaHandlerDescription( + media, &handler_type, NULL); + _IA_HANDLE_ERROR_MP4(err); + err = ISONewHandle(0, &decoder_cfg_hdl); + _IA_HANDLE_ERROR_MP4(err); + err = ISONewHandle(0, &sample_hdl); + _IA_HANDLE_ERROR_MP4(err); + err = ISOCreateTrackReader(trak, &reader); + _IA_HANDLE_ERROR_MP4(err); + } +#endif } - +#ifndef SUPPORT_MP4 if (!strncmp((const char *)argv[i], "-imeta:", 7)) { pWORD8 pb_arg_val = (pWORD8)argv[i] + 7; @@ -2367,6 +2753,7 @@ int main(WORD32 argc, char *argv[]) { } raw_testing = 1; } +#endif if (!strncmp((const char *)argv[i], "-ofile:", 7)) { pWORD8 pb_arg_val = (pWORD8)argv[i] + 7; @@ -2381,6 +2768,7 @@ int main(WORD32 argc, char *argv[]) { } } +#ifndef SUPPORT_MP4 if ((g_pf_inp == NULL) || (g_pf_out == NULL)) { print_usage(); err_code = IA_TESTBENCH_MFMAN_FATAL_FILE_OPEN_FAILED; @@ -2388,11 +2776,33 @@ int main(WORD32 argc, char *argv[]) { (pWORD8) "Input or Output File", err_code); exit(1); } +#else + if (!mp4_flag) + { + if ((g_pf_inp == NULL) || (g_pf_out == NULL)) { + print_usage(); + err_code = IA_TESTBENCH_MFMAN_FATAL_FILE_OPEN_FAILED; + ixheaacd_error_handler(&ixheaacd_ia_testbench_error_info, + (pWORD8) "Input or Output File", err_code); + exit(1); + } + } + else + { + if (g_pf_out == NULL) { + print_usage(); + err_code = IA_TESTBENCH_MFMAN_FATAL_FILE_OPEN_FAILED; + ixheaacd_error_handler(&ixheaacd_ia_testbench_error_info, + (pWORD8) "Output File", err_code); + exit(1); + } + } +#endif g_w_malloc_count = 0; printf("\n"); - +#ifndef SUPPORT_MP4 for (i = 0; i < argc; i++) { if (!strcmp((pCHAR8)argv[i], "-mp4:1")) { if (g_pf_meta == NULL) { @@ -2404,7 +2814,7 @@ int main(WORD32 argc, char *argv[]) { } } } - +#endif for (i = 0; i < argc; i++) { if (strcmp((pCHAR8)argv[i], "-eld_testing:1")) eld_testing = 0; @@ -2420,12 +2830,29 @@ int main(WORD32 argc, char *argv[]) { if (g_pv_arr_alloc_memory[i]) free(g_pv_arr_alloc_memory[i]); } if (g_pf_out) fclose(g_pf_out); - +#ifndef SUPPORT_MP4 if (g_pf_meta) { fclose(g_pf_meta); metadata_mp4_stsz_size_free(&meta_info); } FileWrapper_Close(g_pf_inp); +#else + if (!mp4_flag) + { + FileWrapper_Close(g_pf_inp); + } + else + { + err = ISODisposeHandle(sample_hdl); + _IA_HANDLE_ERROR_MP4(err); + err = ISODisposeHandle(decoder_cfg_hdl); + _IA_HANDLE_ERROR_MP4(err); + err = ISODisposeTrackReader(reader); + _IA_HANDLE_ERROR_MP4(err); + err = ISODisposeMovie(moov); + _IA_HANDLE_ERROR_MP4(err); + } +#endif mpeg_d_drc_on = 0; return IA_NO_ERROR; diff --git a/test/decoder/xaacdec.cmake b/test/decoder/xaacdec.cmake index 51f8fed..608760f 100644 --- a/test/decoder/xaacdec.cmake +++ b/test/decoder/xaacdec.cmake @@ -5,23 +5,44 @@ list(APPEND XAACDEC_SRCS "${XAAC_ROOT}/test/decoder/ixheaacd_error.c" set(LIBXAACDEC_INCLUDES ${XAAC_ROOT}/decoder ${XAAC_ROOT}/test/decoder/ ${XAAC_ROOT}/decoder/drc_src) -include_directories(${LIBXAACDEC_INCLUDES}) +if(SUPPORT_MP4) + set(LIBISOMEDIA_INCLUDES $(XAAC_ROOT)/../isobmff/IsoLib/libisomediafile/src) + + set(LIBISOOSW32_INCLUDES $(XAAC_ROOT)/../isobmff/IsoLib/libisomediafile/w32) + + include_directories(${LIBXAACDEC_INCLUDES} ${LIBISOMEDIA_INCLUDES} ${LIBISOOSW32_INCLUDES}) +else() + include_directories(${LIBXAACDEC_INCLUDES}) +endif() libxaac_add_executable(xaacdec libxaacdec SOURCES ${XAACDEC_SRCS} INCLUDES ${LIBXAACDEC_INCLUDES}) +if(SUPPORT_MP4) + include_external_msproject(libisomediafile + ${XAAC_ROOT}/../isobmff/build/IsoLib/libisomediafile/libisomediafile.vcxproj) + + add_dependencies(xaacdec libisomediafile) +endif() + +set(COMMON_FLAGS "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32") + +if(SUPPORT_MP4) + set(MP4_FLAG "-DSUPPORT_MP4") +endif() + if(MSVC) set_target_properties( xaacdec PROPERTIES COMPILE_FLAGS - "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32 -D_CRT_SECURE_NO_WARNINGS" + "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32 -D_CRT_SECURE_NO_WARNINGS ${MP4_FLAG}" ) else() set_target_properties( xaacdec PROPERTIES COMPILE_FLAGS - "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32" + "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32 ${MP4_FLAG}" ) endif() From bc0609771de6028bac0e6b24b19ea9dcd0349bf6 Mon Sep 17 00:00:00 2001 From: Rumaan Khan <100922@ittiam.com> Date: Tue, 1 Jul 2025 15:56:13 +0530 Subject: [PATCH 2/3] add supp for linux --- test/decoder/xaacdec.cmake | 54 +++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/test/decoder/xaacdec.cmake b/test/decoder/xaacdec.cmake index 608760f..26307bf 100644 --- a/test/decoder/xaacdec.cmake +++ b/test/decoder/xaacdec.cmake @@ -1,48 +1,70 @@ -list(APPEND XAACDEC_SRCS "${XAAC_ROOT}/test/decoder/ixheaacd_error.c" - "${XAAC_ROOT}/test/decoder/ixheaacd_fileifc.c" "${XAAC_ROOT}/test/decoder/ixheaacd_main.c" - "${XAAC_ROOT}/test/decoder/ixheaacd_metadata_read.c") +list(APPEND XAACDEC_SRCS + "${XAAC_ROOT}/test/decoder/ixheaacd_error.c" + "${XAAC_ROOT}/test/decoder/ixheaacd_fileifc.c" + "${XAAC_ROOT}/test/decoder/ixheaacd_main.c" + "${XAAC_ROOT}/test/decoder/ixheaacd_metadata_read.c" +) -set(LIBXAACDEC_INCLUDES ${XAAC_ROOT}/decoder ${XAAC_ROOT}/test/decoder/ - ${XAAC_ROOT}/decoder/drc_src) +set(LIBXAACDEC_INCLUDES + ${XAAC_ROOT}/decoder + ${XAAC_ROOT}/test/decoder/ + ${XAAC_ROOT}/decoder/drc_src +) if(SUPPORT_MP4) - set(LIBISOMEDIA_INCLUDES $(XAAC_ROOT)/../isobmff/IsoLib/libisomediafile/src) + set(LIBISOMEDIA_INCLUDES "${XAAC_ROOT}/../isobmff/IsoLib/libisomediafile/src") - set(LIBISOOSW32_INCLUDES $(XAAC_ROOT)/../isobmff/IsoLib/libisomediafile/w32) - - include_directories(${LIBXAACDEC_INCLUDES} ${LIBISOMEDIA_INCLUDES} ${LIBISOOSW32_INCLUDES}) + # Platform-specific includes + if(MSVC) + set(LIBISOOSW32_INCLUDES "${XAAC_ROOT}/../isobmff/IsoLib/libisomediafile/w32") + include_directories(${LIBXAACDEC_INCLUDES} ${LIBISOMEDIA_INCLUDES} ${LIBISOOSW32_INCLUDES}) + else() + set(LIBISOMEDIA_PLATFORM_INCLUDES ${XAAC_ROOT}/../isobmff/IsoLib/libisomediafile/linux) + include_directories(${LIBXAACDEC_INCLUDES} ${LIBISOMEDIA_INCLUDES} ${LIBISOMEDIA_PLATFORM_INCLUDES}) + endif() else() include_directories(${LIBXAACDEC_INCLUDES}) endif() -libxaac_add_executable(xaacdec libxaacdec SOURCES ${XAACDEC_SRCS} INCLUDES - ${LIBXAACDEC_INCLUDES}) +# Add xaacdec executable +libxaac_add_executable(xaacdec libxaacdec SOURCES ${XAACDEC_SRCS} INCLUDES ${LIBXAACDEC_INCLUDES}) +# Platform-specific linking of MP4 library if(SUPPORT_MP4) - include_external_msproject(libisomediafile - ${XAAC_ROOT}/../isobmff/build/IsoLib/libisomediafile/libisomediafile.vcxproj) + if(MSVC) + # Use Visual Studio project on Windows + include_external_msproject(libisomediafile + ${XAAC_ROOT}/../isobmff/build/IsoLib/libisomediafile/libisomediafile.vcxproj) - add_dependencies(xaacdec libisomediafile) + add_dependencies(xaacdec libisomediafile) + + else() + # Linux: link prebuilt static .a library + set(LIBISOMEDIA_LIB_PATH "${XAAC_ROOT}/../isobmff/lib/liblibisomediafile.a") + target_link_libraries(xaacdec ${LIBISOMEDIA_LIB_PATH}) + endif() endif() +# Common compile flags set(COMMON_FLAGS "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32") if(SUPPORT_MP4) set(MP4_FLAG "-DSUPPORT_MP4") endif() +# Apply compile flags per platform if(MSVC) set_target_properties( xaacdec PROPERTIES COMPILE_FLAGS - "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32 -D_CRT_SECURE_NO_WARNINGS ${MP4_FLAG}" + "${COMMON_FLAGS} -D_CRT_SECURE_NO_WARNINGS ${MP4_FLAG}" ) else() set_target_properties( xaacdec PROPERTIES COMPILE_FLAGS - "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32 ${MP4_FLAG}" + "${COMMON_FLAGS} ${MP4_FLAG}" ) endif() From ee7ac593ae15174bd66ec0ad854d9f3cd13be66a Mon Sep 17 00:00:00 2001 From: Akshay Ragir <100833@ittiam.com> Date: Wed, 23 Jul 2025 10:56:30 +0530 Subject: [PATCH 3/3] WIP: Loudness leveling support for decoder --- cmake/utils.cmake | 1 + decoder/drc_src/impd_drc_api.c | 8 +++- decoder/drc_src/impd_drc_api_struct_def.h | 3 ++ decoder/drc_src/impd_drc_common.h | 3 ++ decoder/drc_src/impd_drc_config_params.h | 3 ++ decoder/drc_src/impd_drc_dynamic_payload.c | 40 +++++++++++++++++++ decoder/drc_src/impd_drc_init.c | 26 ++++++++---- decoder/drc_src/impd_drc_interface.h | 5 +++ decoder/drc_src/impd_drc_interface_decoder.c | 17 +++++--- decoder/drc_src/impd_drc_parser.h | 4 ++ decoder/drc_src/impd_drc_selection_process.h | 4 ++ ...d_drc_selection_process_drcset_selection.c | 15 +++++++ .../drc_src/impd_drc_selection_process_init.c | 8 ++++ decoder/drc_src/impd_drc_static_payload.c | 7 ++++ decoder/drc_src/impd_drc_struct.h | 3 ++ decoder/ixheaacd_aac_config.h | 4 ++ decoder/ixheaacd_api.c | 24 ++++++++++- decoder/ixheaacd_error_codes.h | 5 ++- decoder/ixheaacd_struct_def.h | 3 ++ fuzzer/xaac_dec_fuzzer.cpp | 13 ++++++ test/decoder/impd_drc_config_params.h | 4 +- test/decoder/ixheaacd_error.c | 14 ++++++- test/decoder/ixheaacd_main.c | 38 +++++++++++++++++- test/decoder/xaacdec.cmake | 2 +- 24 files changed, 232 insertions(+), 22 deletions(-) diff --git a/cmake/utils.cmake b/cmake/utils.cmake index 922c8d0..5d9cd37 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -50,6 +50,7 @@ function(libxaac_add_definitions) elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") add_definitions(-DX86_64 -D_X86_64_) endif() + add_definitions(-DLOUDNESS_LEVELING_SUPPORT) endfunction() # Adds libraries needed for executables diff --git a/decoder/drc_src/impd_drc_api.c b/decoder/drc_src/impd_drc_api.c index 94ddccc..529d1a5 100644 --- a/decoder/drc_src/impd_drc_api.c +++ b/decoder/drc_src/impd_drc_api.c @@ -246,7 +246,7 @@ IA_ERRORCODE ia_drc_dec_api(pVOID p_ia_drc_dec_obj, WORD32 i_cmd, WORD32 i_idx, case IA_API_CMD_SET_CONFIG_PARAM: { switch (i_idx) { case IA_DRC_DEC_CONFIG_PARAM_SAMP_FREQ: { - if (*pus_value < 8000 || *pus_value > 96000) { + if (*pus_value <= 0 || *pus_value > 96000) { return IA_DRC_DEC_CONFIG_NON_FATAL_INVALID_SAMP_FREQ; } p_obj_drc->str_config.sampling_rate = *pus_value; @@ -328,6 +328,12 @@ IA_ERRORCODE ia_drc_dec_api(pVOID p_ia_drc_dec_obj, WORD32 i_cmd, WORD32 i_idx, p_obj_drc->str_config.compress_set = 1; break; } +#ifdef LOUDNESS_LEVELING_SUPPORT + case IA_DRC_DEC_CONFIG_DRC_LOUDNESS_LEVELING: { + p_obj_drc->str_config.loudness_leveling_flag = *pus_value; + break; + } +#endif default: { return -1; } } break; diff --git a/decoder/drc_src/impd_drc_api_struct_def.h b/decoder/drc_src/impd_drc_api_struct_def.h index a753465..de1a637 100644 --- a/decoder/drc_src/impd_drc_api_struct_def.h +++ b/decoder/drc_src/impd_drc_api_struct_def.h @@ -63,6 +63,9 @@ typedef struct ia_drc_config_struct { WORD32 apply_crossfade; WORD32 is_config_changed; WORD32 ln_dbgain_prev; +#ifdef LOUDNESS_LEVELING_SUPPORT + WORD32 loudness_leveling_flag; +#endif } ia_drc_config_struct; /* DRC bitsteam handler */ diff --git a/decoder/drc_src/impd_drc_common.h b/decoder/drc_src/impd_drc_common.h index bf0f9dd..db57fe2 100644 --- a/decoder/drc_src/impd_drc_common.h +++ b/decoder/drc_src/impd_drc_common.h @@ -193,6 +193,9 @@ extern "C" { #define UNIDRCCONFEXT_V1 0x2 #define UNIDRCLOUDEXT_EQ 0x1 #define UNIDRCINTERFACEEXT_EQ 0x1 +#ifdef LOUDNESS_LEVELING_SUPPORT +#define UNIDRCCONFEXT_LEVELING (0x4) +#endif #define LOUD_EQ_REQUEST_OFF 0x0 #define LOUD_EQ_REQUEST_LIGHT 0x1 diff --git a/decoder/drc_src/impd_drc_config_params.h b/decoder/drc_src/impd_drc_config_params.h index b0d19c5..2bc6ab7 100644 --- a/decoder/drc_src/impd_drc_config_params.h +++ b/decoder/drc_src/impd_drc_config_params.h @@ -46,4 +46,7 @@ #define IA_DRC_DEC_CONFIG_DRC_COMPRESS 0x0016 #define IA_DRC_DEC_CONFIG_PARAM_APPLY_CROSSFADE 0x0017 #define IA_DRC_DEC_CONFIG_PARAM_CONFIG_CHANGED 0x0018 +#ifdef LOUDNESS_LEVELING_SUPPORT +#define IA_DRC_DEC_CONFIG_DRC_LOUDNESS_LEVELING 0x0019 +#endif #endif diff --git a/decoder/drc_src/impd_drc_dynamic_payload.c b/decoder/drc_src/impd_drc_dynamic_payload.c index 3c0cbb8..e005198 100644 --- a/decoder/drc_src/impd_drc_dynamic_payload.c +++ b/decoder/drc_src/impd_drc_dynamic_payload.c @@ -28,6 +28,10 @@ #include "impd_drc_parser.h" #include "impd_drc_filter_bank.h" #include "impd_drc_rom.h" +#ifdef LOUDNESS_LEVELING_SUPPORT +#include "impd_drc_error_codes.h" +#include "ixheaacd_error_codes.h" +#endif WORD32 impd_parse_loud_eq_instructions( ia_bit_buf_struct* it_bit_buff, ia_loud_eq_instructions_struct* loud_eq_instructions); @@ -646,6 +650,42 @@ WORD32 impd_parse_drc_ext_v1(ia_bit_buf_struct* it_bit_buff, return 0; } +#ifdef LOUDNESS_LEVELING_SUPPORT +IA_ERROR_CODE impd_leveling_instructions(ia_bit_buf_struct* it_bit_buff, + ia_drc_config* pstr_drc_config) { + WORD32 i; + IA_ERROR_CODE err = IA_NO_ERROR; + WORD32 drc_instruction_uni_drc_count = pstr_drc_config->drc_instructions_uni_drc_count; + + for (i = 0; i < drc_instruction_uni_drc_count; ++i) { + if ((pstr_drc_config->str_drc_instruction_str[i].drc_set_effect & (1 << 11)) != 0) { + pstr_drc_config->str_drc_instruction_str[i].leveling_present = + impd_read_bits_buf(it_bit_buff, 1); + + if (pstr_drc_config->str_drc_instruction_str[i].leveling_present) { + WORD32 ducking_only_drc_set_present = impd_read_bits_buf(it_bit_buff, 1); + + if (ducking_only_drc_set_present) { + pstr_drc_config->drc_instructions_uni_drc_count++; + + if (pstr_drc_config->drc_instructions_uni_drc_count > DRC_INSTRUCTIONS_COUNT_MAX) { + return IA_XHEAAC_DEC_INIT_NONFATAL_MAX_INSTRUCTIONS_ERROR; + } + + err = impd_parse_drc_instructions_uni_drc( + it_bit_buff, 1, pstr_drc_config, + &pstr_drc_config + ->str_drc_instruction_str[pstr_drc_config->drc_instructions_uni_drc_count - + 1]); + if (err) return err; + } + } + } + } + return err; +} +#endif + WORD32 impd_parse_filt_block(ia_bit_buf_struct* it_bit_buff, ia_filt_block_struct* str_filter_block, WORD32 block_count) { diff --git a/decoder/drc_src/impd_drc_init.c b/decoder/drc_src/impd_drc_init.c index 870b759..bc0af38 100644 --- a/decoder/drc_src/impd_drc_init.c +++ b/decoder/drc_src/impd_drc_init.c @@ -58,10 +58,15 @@ impd_drc_dec_interface_process(ia_bit_buf_struct *it_bit_buff, WORD32 *num_bits_read); WORD32 -impd_drc_dec_interface_add_effect_type( - ia_drc_interface_struct *pstr_drc_interface, WORD32 drc_effect_type, - WORD32 target_loudness, WORD32 loud_norm, WORD32 album_mode, FLOAT32 boost, - FLOAT32 compress); +impd_drc_dec_interface_add_effect_type(ia_drc_interface_struct *pstr_drc_interface, + WORD32 drc_effect_type, WORD32 target_loudness, + WORD32 loud_norm, WORD32 album_mode, FLOAT32 boost, + FLOAT32 compress +#ifdef LOUDNESS_LEVELING_SUPPORT + , + WORD32 loudness_leveling_flag +#endif +); #define BITSTREAM_FILE_FORMAT_SPLIT 1 #define LIM_DEFAULT_THRESHOLD (0.89125094f) @@ -411,10 +416,15 @@ IA_ERRORCODE impd_drc_init(ia_drc_api_struct *p_obj_drc) { p_obj_drc->str_config.compress = 1.0f; err_code = impd_drc_dec_interface_add_effect_type( - p_obj_drc->str_payload.pstr_drc_interface, - p_obj_drc->str_config.effect_type, p_obj_drc->str_config.target_loudness, - p_obj_drc->str_config.loud_norm_flag, p_obj_drc->str_config.album_mode, - p_obj_drc->str_config.boost, p_obj_drc->str_config.compress); + p_obj_drc->str_payload.pstr_drc_interface, p_obj_drc->str_config.effect_type, + p_obj_drc->str_config.target_loudness, p_obj_drc->str_config.loud_norm_flag, + p_obj_drc->str_config.album_mode, p_obj_drc->str_config.boost, + p_obj_drc->str_config.compress +#ifdef LOUDNESS_LEVELING_SUPPORT + , + p_obj_drc->str_config.loudness_leveling_flag +#endif + ); if (err_code != IA_NO_ERROR) return err_code; diff --git a/decoder/drc_src/impd_drc_interface.h b/decoder/drc_src/impd_drc_interface.h index a0e7039..c05ae3b 100644 --- a/decoder/drc_src/impd_drc_interface.h +++ b/decoder/drc_src/impd_drc_interface.h @@ -42,6 +42,11 @@ typedef struct { typedef struct { WORD32 interface_ext_count; ia_specific_interface_extension_struct specific_interface_ext[EXT_COUNT_MAX]; + +#ifdef LOUDNESS_LEVELING_SUPPORT + WORD32 loudness_leveling_on; +#endif + WORD32 loudness_eq_parameter_interface_flag; WORD32 eq_ctrl_interface_flag; ia_loudness_eq_parameter_interface_struct loudness_eq_parameter_interface; diff --git a/decoder/drc_src/impd_drc_interface_decoder.c b/decoder/drc_src/impd_drc_interface_decoder.c index 557ea2f..b7bd430 100644 --- a/decoder/drc_src/impd_drc_interface_decoder.c +++ b/decoder/drc_src/impd_drc_interface_decoder.c @@ -29,10 +29,15 @@ #include "impd_drc_parser_interface.h" WORD32 -impd_drc_dec_interface_add_effect_type( - ia_drc_interface_struct* pstr_drc_interface, WORD32 drc_effect_type, - WORD32 target_loudness, WORD32 loud_norm, WORD32 album_mode, FLOAT32 boost, - FLOAT32 compress) { +impd_drc_dec_interface_add_effect_type(ia_drc_interface_struct* pstr_drc_interface, + WORD32 drc_effect_type, WORD32 target_loudness, + WORD32 loud_norm, WORD32 album_mode, FLOAT32 boost, + FLOAT32 compress +#ifdef LOUDNESS_LEVELING_SUPPORT + , + WORD32 loudness_leveling_flag +#endif +) { WORD32 err = 0; WORD32 i = 0; @@ -65,7 +70,9 @@ impd_drc_dec_interface_add_effect_type( } pstr_drc_interface->loudness_norm_ctrl_interface.target_loudness = (FLOAT32)target_loudness; - +#ifdef LOUDNESS_LEVELING_SUPPORT + pstr_drc_interface->drc_uni_interface_ext.loudness_leveling_on = loudness_leveling_flag; +#endif pstr_drc_interface->loudness_norm_parameter_interface_flag = 1; pstr_drc_interface->loudness_norm_param_interface.album_mode = album_mode; pstr_drc_interface->loudness_norm_param_interface.peak_limiter = 0; diff --git a/decoder/drc_src/impd_drc_parser.h b/decoder/drc_src/impd_drc_parser.h index 75c548b..92018a0 100644 --- a/decoder/drc_src/impd_drc_parser.h +++ b/decoder/drc_src/impd_drc_parser.h @@ -73,6 +73,10 @@ impd_parse_drc_ext_v1(ia_bit_buf_struct* it_bit_buff, ia_drc_config* drc_config, ia_drc_config_ext* str_drc_config_ext); +#ifdef LOUDNESS_LEVELING_SUPPORT +WORD32 impd_leveling_instructions(ia_bit_buf_struct* it_bit_buff, ia_drc_config* pstr_drc_config); +#endif + WORD32 impd_parse_drc_config(ia_bit_buf_struct* it_bit_buff, ia_drc_params_bs_dec_struct* ia_drc_params_struct, diff --git a/decoder/drc_src/impd_drc_selection_process.h b/decoder/drc_src/impd_drc_selection_process.h index 4fdabe3..fba45e0 100644 --- a/decoder/drc_src/impd_drc_selection_process.h +++ b/decoder/drc_src/impd_drc_selection_process.h @@ -82,6 +82,10 @@ typedef struct ia_drc_sel_proc_params_struct { FLOAT32 playback_gain; WORD32 eq_set_purpose_request; +#ifdef LOUDNESS_LEVELING_SUPPORT + WORD32 loudness_leveling_on; +#endif + FLOAT32 boost; FLOAT32 compress; WORD32 drc_characteristic_target; diff --git a/decoder/drc_src/impd_drc_selection_process_drcset_selection.c b/decoder/drc_src/impd_drc_selection_process_drcset_selection.c index 153e2f5..9317e8c 100644 --- a/decoder/drc_src/impd_drc_selection_process_drcset_selection.c +++ b/decoder/drc_src/impd_drc_selection_process_drcset_selection.c @@ -30,6 +30,9 @@ #include "impd_drc_loudness_control.h" #include "impd_drc_filter_bank.h" #include "impd_drc_rom.h" +#ifdef LOUDNESS_LEVELING_SUPPORT +#include "ixheaac_error_standards.h" +#endif static const WORD32 effect_types_request_table[] = { EFFECT_BIT_NIGHT, EFFECT_BIT_NOISY, EFFECT_BIT_LIMITED, @@ -170,6 +173,12 @@ WORD32 impd_get_ducking_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc) { (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) { for (k = 0; k < str_drc_instruction_str->dwnmix_id_count; k++) { if (str_drc_instruction_str->downmix_id[k] == requested_dwnmix_id) { +#ifdef LOUDNESS_LEVELING_SUPPORT + if (drc_instructions_index != -1) break; + if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.loudness_leveling_on == 0 && + str_drc_instruction_str->leveling_present == 1) + continue; +#endif drc_instructions_index = n; } } @@ -186,6 +195,12 @@ WORD32 impd_get_ducking_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc) { (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) { for (k = 0; k < str_drc_instruction_str->dwnmix_id_count; k++) { if (str_drc_instruction_str->downmix_id[k] == ID_FOR_BASE_LAYOUT) { +#ifdef LOUDNESS_LEVELING_SUPPORT + if (drc_instructions_index != -1) break; + if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.loudness_leveling_on == 0 && + str_drc_instruction_str->leveling_present == 1) + continue; +#endif drc_instructions_index = n; } } diff --git a/decoder/drc_src/impd_drc_selection_process_init.c b/decoder/drc_src/impd_drc_selection_process_init.c index 4a1ae63..667a4b6 100644 --- a/decoder/drc_src/impd_drc_selection_process_init.c +++ b/decoder/drc_src/impd_drc_selection_process_init.c @@ -104,6 +104,10 @@ WORD32 impd_drc_sel_proc_init_dflt( pstr_drc_uni_sel_proc->eq_inst_index[0] = -1; pstr_drc_uni_sel_proc->eq_inst_index[1] = -1; pstr_drc_uni_sel_proc->sel_proc_request_flag = 1; + +#ifdef LOUDNESS_LEVELING_SUPPORT + pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.loudness_leveling_on = 1; +#endif } else { return 1; } @@ -133,6 +137,10 @@ VOID impd_drc_sel_proc_init_interface_params( WORD32 i, j; if (pstr_drc_uni_sel_proc != NULL && pstr_drc_interface != NULL) { +#ifdef LOUDNESS_LEVELING_SUPPORT + pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.loudness_leveling_on = + pstr_drc_interface->drc_uni_interface_ext.loudness_leveling_on; +#endif if (pstr_drc_interface->system_interface_flag) { if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params .target_config_request_type != diff --git a/decoder/drc_src/impd_drc_static_payload.c b/decoder/drc_src/impd_drc_static_payload.c index 54e5162..816b9c9 100644 --- a/decoder/drc_src/impd_drc_static_payload.c +++ b/decoder/drc_src/impd_drc_static_payload.c @@ -954,6 +954,13 @@ impd_parse_drc_config_ext(ia_bit_buf_struct* it_bit_buff, drc_config, str_drc_config_ext); if (err) return (err); break; + +#ifdef LOUDNESS_LEVELING_SUPPORT + case UNIDRCCONFEXT_LEVELING: + err = impd_leveling_instructions(it_bit_buff, drc_config); + if (err) return err; + break; +#endif default: for (i = 0; i < str_drc_config_ext->ext_bit_size[k]; i++) { impd_read_bits_buf(it_bit_buff, 1); diff --git a/decoder/drc_src/impd_drc_struct.h b/decoder/drc_src/impd_drc_struct.h index ea07644..a8e63bc 100644 --- a/decoder/drc_src/impd_drc_struct.h +++ b/decoder/drc_src/impd_drc_struct.h @@ -424,6 +424,9 @@ typedef struct { WORD32 gain_set_idx_of_ch_group_parametric_drc[CHANNEL_GROUP_COUNT_MAX]; WORD32 parametric_drc_look_ahead_samples[CHANNEL_GROUP_COUNT_MAX]; WORD32 parametric_drc_look_ahead_samples_max; +#ifdef LOUDNESS_LEVELING_SUPPORT + WORD32 leveling_present; +#endif } ia_drc_instructions_struct; typedef struct { diff --git a/decoder/ixheaacd_aac_config.h b/decoder/ixheaacd_aac_config.h index b31cee3..0e6e072 100644 --- a/decoder/ixheaacd_aac_config.h +++ b/decoder/ixheaacd_aac_config.h @@ -65,6 +65,10 @@ #define IA_XHEAAC_DEC_CONFIG_PARAM_ESBR 0x0028 +#ifdef LOUDNESS_LEVELING_SUPPORT +#define IA_XHEAAC_DEC_CONFIG_PARAM_DRC_LOUDNESS_LEVELING 0x0029 +#endif + #define IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ IA_XHEAAC_DEC_CONFIG_PARAM_PCM_WDSZ #define IA_ENHAACPLUS_DEC_CONFIG_PARAM_SAMP_FREQ IA_XHEAAC_DEC_CONFIG_PARAM_SAMP_FREQ #define IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS IA_XHEAAC_DEC_CONFIG_PARAM_NUM_CHANNELS diff --git a/decoder/ixheaacd_api.c b/decoder/ixheaacd_api.c index 1608968..31157d2 100644 --- a/decoder/ixheaacd_api.c +++ b/decoder/ixheaacd_api.c @@ -480,7 +480,9 @@ IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_xheaac_dec_obj, WORD32 i_cmd, p_obj_exhaacplus_dec->aac_config.ui_drc_set = 0; p_obj_exhaacplus_dec->aac_config.ui_flush_cmd = 0; p_obj_exhaacplus_dec->aac_config.output_level = -1; - +#ifdef LOUDNESS_LEVELING_SUPPORT + p_obj_exhaacplus_dec->aac_config.ui_loudness_leveling_flag = 1; +#endif p_obj_exhaacplus_dec->aac_config.ui_max_channels = 6; p_obj_exhaacplus_dec->aac_config.ui_coupling_channel = 0; @@ -789,6 +791,16 @@ IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_xheaac_dec_obj, WORD32 i_cmd, p_obj_exhaacplus_dec->aac_config.ui_enh_sbr = *pui_value_signed; break; } +#ifdef LOUDNESS_LEVELING_SUPPORT + case IA_XHEAAC_DEC_CONFIG_PARAM_DRC_LOUDNESS_LEVELING: { + if (((*pui_value_signed) != 0) && ((*pui_value_signed) != 1)) { + p_obj_exhaacplus_dec->aac_config.ui_loudness_leveling_flag = 1; + return (IA_XHEAAC_DEC_CONFIG_NONFATAL_INVALID_LOUDNESS_LEVELING_FLAG); + } + p_obj_exhaacplus_dec->aac_config.ui_loudness_leveling_flag = *pui_value_signed; + break; + } +#endif default: { return IA_XHEAAC_DEC_API_FATAL_INVALID_CONFIG_PARAM; } } break; @@ -931,7 +943,15 @@ IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_xheaac_dec_obj, WORD32 i_cmd, } else { *pui_value = AOT_AAC_LC; } - } else { + } +#ifdef LOUDNESS_LEVELING_SUPPORT + else if (IA_XHEAAC_DEC_CONFIG_PARAM_DRC_LOUDNESS_LEVELING == i_idx) { + WORD32 *ui_value = + (WORD32 *)(&p_obj_exhaacplus_dec->aac_config.ui_loudness_leveling_flag); + *pui_value = *ui_value; + } +#endif + else { return IA_XHEAAC_DEC_API_FATAL_INVALID_CONFIG_PARAM; } break; diff --git a/decoder/ixheaacd_error_codes.h b/decoder/ixheaacd_error_codes.h index 2e4c985..4d2a2fc 100644 --- a/decoder/ixheaacd_error_codes.h +++ b/decoder/ixheaacd_error_codes.h @@ -63,6 +63,9 @@ #define IA_XHEAAC_DEC_CONFIG_NONFATAL_INVALID_ESBR_HQ_FLAG 0x00000815 #define IA_XHEAAC_DEC_CONFIG_NONFATAL_INVALID_FRAMELENGTHFLAG 0x00000816 #define IA_XHEAAC_DEC_CONFIG_NONFATAL_INVALID_ESBR_FLAG 0x00000817 +#ifdef LOUDNESS_LEVELING_SUPPORT +#define IA_XHEAAC_DEC_CONFIG_NONFATAL_INVALID_LOUDNESS_LEVELING_FLAG 0x00000818 +#endif /* Fatal Errors */ #define IA_XHEAAC_DEC_CONFIG_FATAL_INVALID_SAMPLE_RATE 0xFFFF8800 @@ -75,7 +78,7 @@ #define IA_XHEAAC_DEC_INIT_NONFATAL_EC_INIT_FAIL 0x00001002 #define IA_XHEAAC_DEC_INIT_NONFATAL_INSUFFICIENT_INPUT_BYTES 0x00001003 #define IA_XHEAAC_DEC_INIT_NONFATAL_DECODE_FRAME_ERROR 0x00001004 - +#define IA_XHEAAC_DEC_INIT_NONFATAL_MAX_INSTRUCTIONS_ERROR 0x00001005 /* Fatal Errors */ #define IA_XHEAAC_DEC_INIT_FATAL_DEC_INIT_FAIL 0xFFFF9000 #define IA_XHEAAC_DEC_INIT_FATAL_EO_INPUT_REACHED 0xFFFF9001 diff --git a/decoder/ixheaacd_struct_def.h b/decoder/ixheaacd_struct_def.h index a098594..fea3b56 100644 --- a/decoder/ixheaacd_struct_def.h +++ b/decoder/ixheaacd_struct_def.h @@ -137,6 +137,9 @@ typedef struct { WORD32 ui_err_conceal; FLAG first_frame; +#ifdef LOUDNESS_LEVELING_SUPPORT + WORD32 ui_loudness_leveling_flag; +#endif } ia_aac_dec_config_struct; typedef struct ia_aac_dec_state_struct { diff --git a/fuzzer/xaac_dec_fuzzer.cpp b/fuzzer/xaac_dec_fuzzer.cpp index 555ba29..98fd5c4 100644 --- a/fuzzer/xaac_dec_fuzzer.cpp +++ b/fuzzer/xaac_dec_fuzzer.cpp @@ -240,6 +240,10 @@ enum { DRC_BOOST_OFFSET, DRC_COMPRESS_OFFSET, DRC_EFFECT_OFFSET +#ifdef LOUDNESS_LEVELING_SUPPORT + , + DRC_LOUDNESS_LEVELING_OFFSET +#endif }; IA_ERRORCODE Codec::initXAACDrc(const uint8_t* data, size_t size) { @@ -295,6 +299,15 @@ IA_ERRORCODE Codec::initXAACDrc(const uint8_t* data, size_t size) { err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE, &ui_drc_val); +#ifdef LOUDNESS_LEVELING_SUPPORT + // DRC_LOUDNESS_LEVELING_FLAG + size_t flagOffset = std::min((size_t)DRC_LOUDNESS_LEVELING_OFFSET, size - 1); + uint8_t loudnessFlag = data[flagOffset]; + ui_drc_val = (unsigned int)loudnessFlag; + err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, + IA_XHEAAC_DEC_CONFIG_PARAM_DRC_LOUDNESS_LEVELING, &ui_drc_val); +#endif + return IA_NO_ERROR; } diff --git a/test/decoder/impd_drc_config_params.h b/test/decoder/impd_drc_config_params.h index 36ca1fe..47f7873 100644 --- a/test/decoder/impd_drc_config_params.h +++ b/test/decoder/impd_drc_config_params.h @@ -44,7 +44,9 @@ #define IA_DRC_DEC_CONFIG_PARAM_APPLY_CROSSFADE 0x0017 #define IA_DRC_DEC_CONFIG_PARAM_CONFIG_CHANGED 0x0018 - +#ifdef LOUDNESS_LEVELING_SUPPORT +#define IA_DRC_DEC_CONFIG_DRC_LOUDNESS_LEVELING 0x0019 +#endif #define IA_API_CMD_SET_INPUT_BYTES_BS 0x0026 #define IA_API_CMD_SET_INPUT_BYTES_IC_BS 0x0027 #define IA_API_CMD_SET_INPUT_BYTES_IL_BS 0x0029 diff --git a/test/decoder/ixheaacd_error.c b/test/decoder/ixheaacd_error.c index 78b96ef..82d4b5a 100644 --- a/test/decoder/ixheaacd_error.c +++ b/test/decoder/ixheaacd_error.c @@ -75,7 +75,12 @@ pWORD8 ixheaacd_ppb_config_non_fatal[IA_MAX_ERROR_SUB_CODE] = { (pWORD8) "Invalid target loudness value", (pWORD8) "Invalid HQ eSBR flag option. Setting to default 0", (pWORD8) "Invalid frame length flag option. Setting to default 0", - (pWORD8) "Invalid eSBR flag option. Setting to default 1"}; + (pWORD8) "Invalid eSBR flag option. Setting to default 1" +#ifdef LOUDNESS_LEVELING_SUPPORT + , + (pWORD8) "Invalid Loudness leveling flag option. Setting to default 1" +#endif +}; /* Fatal Errors */ pWORD8 ixheaacd_ppb_config_fatal[IA_MAX_ERROR_SUB_CODE] = { (pWORD8) "Invalid Sample rate specified for RAW decoding"}; @@ -87,7 +92,12 @@ pWORD8 ixheaacd_ppb_config_fatal[IA_MAX_ERROR_SUB_CODE] = { pWORD8 ixheaacd_ppb_init_non_fatal[IA_MAX_ERROR_SUB_CODE] = { (pWORD8) "Header not found at the beginning of input data continuing syncing", (pWORD8) "Invalid number of QMF bands", (pWORD8) "Decoder initialization failed", - (pWORD8) "Input bytes insufficient for decoding", (pWORD8) "Error in AAC decoding"}; + (pWORD8) "Input bytes insufficient for decoding", (pWORD8) "Error in AAC decoding" +#ifdef LOUDNESS_LEVELING_SUPPORT + , + (pWORD8) "DRC instruction count exceeded" +#endif +}; /* Fatal Errors */ pWORD8 ixheaacd_ppb_init_fatal[IA_MAX_ERROR_SUB_CODE] = { (pWORD8) "AAC Decoder initialization failed", diff --git a/test/decoder/ixheaacd_main.c b/test/decoder/ixheaacd_main.c index a96cf0e..9d0429d 100644 --- a/test/decoder/ixheaacd_main.c +++ b/test/decoder/ixheaacd_main.c @@ -689,6 +689,17 @@ IA_ERRORCODE ixheaacd_set_config_param(WORD32 argc, pWORD8 argv[], _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); ec_enable = ui_err_conceal; } +#ifdef LOUDNESS_LEVELING_SUPPORT + /* For loudness leveling*/ + if (!strncmp((pCHAR8)argv[i], "-loudness_leveling:", 19)) { + pCHAR8 pb_arg_val = (pCHAR8)(argv[i] + 19); + UWORD32 loudness_leveling_flag = atoi(pb_arg_val); + err_code = (*p_ia_process_api)(p_ia_process_api_obj, IA_API_CMD_SET_CONFIG_PARAM, + IA_XHEAAC_DEC_CONFIG_PARAM_DRC_LOUDNESS_LEVELING, + &loudness_leveling_flag); + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + } +#endif } #ifdef SUPPORT_MP4 { @@ -935,7 +946,9 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { WORD32 drc_flag = 0; WORD32 mpegd_drc_present = 0; WORD32 uo_num_chan; - +#ifdef LOUDNESS_LEVELING_SUPPORT + WORD32 i_loudness_leveling_flag = 1; +#endif /* The process API function */ IA_ERRORCODE(*p_ia_process_api) (pVOID p_ia_process_api_obj, WORD32 i_cmd, WORD32 i_idx, pVOID pv_value); @@ -1597,6 +1610,22 @@ int ixheaacd_main_process(WORD32 argc, pWORD8 argv[]) { _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); } +#ifdef LOUDNESS_LEVELING_SUPPORT + /*Set loudness leveling */ + + { + err_code = (*p_ia_process_api)(pv_ia_process_api_obj, IA_API_CMD_GET_CONFIG_PARAM, + IA_XHEAAC_DEC_CONFIG_PARAM_DRC_LOUDNESS_LEVELING, + &i_loudness_leveling_flag); + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + + err_code = + ia_drc_dec_api(pv_ia_drc_process_api_obj, IA_API_CMD_SET_CONFIG_PARAM, + IA_DRC_DEC_CONFIG_DRC_LOUDNESS_LEVELING, &i_loudness_leveling_flag); + _IA_HANDLE_ERROR(p_proc_err_info, (pWORD8) "", err_code); + } +#endif + /*Set loud_norm_flag*/ { err_code = (*p_ia_process_api)( @@ -2582,6 +2611,9 @@ void print_usage() { printf("\n[-peak_limiter_off:]"); printf("\n[-err_conceal:]"); printf("\n[-esbr:]"); +#ifdef LOUDNESS_LEVELING_SUPPORT + printf("\n[-loudness_leveling:]"); +#endif printf("\n\nwhere, \n is the input AAC-LC/HE-AACv1/HE-AACv2//AAC-LD/AAC-ELD/AAC-ELDv2/USAC file name"); printf("\n is a text file which contains metadata."); printf("\n To be given when -mp4:1 is enabled"); @@ -2638,6 +2670,10 @@ void print_usage() { printf("\n is to enable / disable error concealment."); printf("\n Default value is 0"); printf("\n is to enable / disable eSBR. Default value is 1\n\n"); +#ifdef LOUDNESS_LEVELING_SUPPORT + printf("\n ] is to enable / disable loudness leveling."); + printf("\n Default value is 1"); +#endif } /*******************************************************************************/ diff --git a/test/decoder/xaacdec.cmake b/test/decoder/xaacdec.cmake index 26307bf..f499ea8 100644 --- a/test/decoder/xaacdec.cmake +++ b/test/decoder/xaacdec.cmake @@ -46,7 +46,7 @@ if(SUPPORT_MP4) endif() # Common compile flags -set(COMMON_FLAGS "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32") +set(COMMON_FLAGS "-UARM_PROFILE_HW -UARM_PROFILE_BOARD -DDRC_ENABLE -DMULTICHANNEL_ENABLE -DECLIPSE -DWIN32 -DLOUDNESS_LEVELING_SUPPORT") if(SUPPORT_MP4) set(MP4_FLAG "-DSUPPORT_MP4")