From cf200f9563e455f734c2670c7802a7cf48998835 Mon Sep 17 00:00:00 2001 From: nu774 Date: Thu, 25 Aug 2016 20:53:14 +0900 Subject: [PATCH] Use our SBR signaling implementation on old libfdkaac --- src/aacenc.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/aacenc.h | 6 +++++ src/main.c | 26 +++++++++++++------ 3 files changed, 95 insertions(+), 8 deletions(-) diff --git a/src/aacenc.c b/src/aacenc.c index a6984fe..8662dbe 100644 --- a/src/aacenc.c +++ b/src/aacenc.c @@ -13,6 +13,13 @@ #include #include "aacenc.h" +int aacenc_is_explicit_bw_compatible_sbr_signaling_available() +{ + LIB_INFO lib_info; + aacenc_get_lib_info(&lib_info); + return lib_info.version > 0x03040900; +} + int aacenc_is_sbr_ratio_available() { #if AACENCODER_LIB_VL0 < 3 || (AACENCODER_LIB_VL0==3 && AACENCODER_LIB_VL1<4) @@ -64,6 +71,70 @@ void aacenc_get_lib_info(LIB_INFO *info) free(lib_info); } +static const unsigned aacenc_sampling_freq_tab[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, 7350, 0, 0, 0 +}; + +static +unsigned sampling_freq_index(unsigned rate) +{ + unsigned i; + for (i = 0; aacenc_sampling_freq_tab[i]; ++i) + if (aacenc_sampling_freq_tab[i] == rate) + return i; + return 0xf; +} + +/* + * Append backward compatible SBR/PS signaling to implicit signaling ASC, + * if SBR/PS is present. + */ +int aacenc_mp4asc(const aacenc_param_t *params, + const uint8_t *asc, uint32_t ascsize, + uint8_t *outasc, uint32_t *outsize) +{ + unsigned asc_sfreq = aacenc_sampling_freq_tab[(asc[0]&0x7)<<1 |asc[1]>>7]; + unsigned shift = aacenc_is_dual_rate_sbr(params); + + switch (params->profile) { + case AOT_SBR: + case AOT_PS: + if (!shift) + break; + if (*outsize < ascsize + 3) + return -1; + memcpy(outasc, asc, ascsize); + /* syncExtensionType:11 (value:0x2b7) */ + outasc[ascsize+0] = 0x2b << 1; + outasc[ascsize+1] = 0x7 << 5; + /* extensionAudioObjectType:5 (value:5)*/ + outasc[ascsize+1] |= 5; + /* sbrPresentFlag:1 (value:1) */ + outasc[ascsize+2] = 0x80; + /* extensionSamplingFrequencyIndex:4 */ + outasc[ascsize+2] |= sampling_freq_index(asc_sfreq << shift) << 3; + if (params->profile == AOT_SBR) { + *outsize = ascsize + 3; + return 0; + } + if (*outsize < ascsize + 5) + return -1; + /* syncExtensionType:11 (value:0x548) */ + outasc[ascsize+2] |= 0x5; + outasc[ascsize+3] = 0x48; + /* psPresentFlag:1 (value:1) */ + outasc[ascsize+4] = 0x80; + *outsize = ascsize + 5; + return 0; + } + if (*outsize < ascsize) + return -1; + memcpy(outasc, asc, ascsize); + *outsize = ascsize; + return 0; +} + static int aacenc_channel_mode(const pcm_sample_description_t *format) { diff --git a/src/aacenc.h b/src/aacenc.h index ec0bea1..2b7d102 100644 --- a/src/aacenc.h +++ b/src/aacenc.h @@ -30,6 +30,8 @@ typedef struct aacenc_frame_t { uint32_t size, capacity; } aacenc_frame_t; +int aacenc_is_explicit_bw_compatible_sbr_signaling_available(); + int aacenc_is_sbr_ratio_available(); int aacenc_is_sbr_active(const aacenc_param_t *params); @@ -38,6 +40,10 @@ int aacenc_is_dual_rate_sbr(const aacenc_param_t *params); void aacenc_get_lib_info(LIB_INFO *info); +int aacenc_mp4asc(const aacenc_param_t *params, + const uint8_t *asc, uint32_t ascsize, + uint8_t *outasc, uint32_t *outsize); + int aacenc_init(HANDLE_AACENCODER *encoder, const aacenc_param_t *params, const pcm_sample_description_t *format, AACENC_InfoStruct *info); diff --git a/src/main.c b/src/main.c index 932019b..a5c7cc8 100644 --- a/src/main.c +++ b/src/main.c @@ -801,12 +801,14 @@ int main(int argc, char **argv) params.sbr_ratio = 2; } scale_shift = aacenc_is_dual_rate_sbr((aacenc_param_t*)¶ms); - params.sbr_signaling = - (params.transport_format == TT_MP4_LOAS) ? 2 : - (params.transport_format == TT_MP4_RAW) ? 1 : 0; - if (sbr_mode && !scale_shift) - params.sbr_signaling = 2; - + params.sbr_signaling = 0; + if (sbr_mode) { + if (params.transport_format == TT_MP4_LOAS || !scale_shift) + params.sbr_signaling = 2; + if (params.transport_format == TT_MP4_RAW && + aacenc_is_explicit_bw_compatible_sbr_signaling_available()) + params.sbr_signaling = 1; + } if (aacenc_init(&encoder, (aacenc_param_t*)¶ms, sample_format, &aacinfo) < 0) goto END; @@ -832,9 +834,17 @@ int main(int argc, char **argv) params.output_fp)) < 0) goto END; m4af_set_num_channels(m4af, 0, sample_format->channels_per_frame); - m4af_set_decoder_specific_info(m4af, 0, - aacinfo.confBuf, aacinfo.confSize); m4af_set_fixed_frame_duration(m4af, 0, framelen >> scale_shift); + if (aacenc_is_explicit_bw_compatible_sbr_signaling_available()) + m4af_set_decoder_specific_info(m4af, 0, + aacinfo.confBuf, aacinfo.confSize); + else { + uint8_t mp4asc[32]; + uint32_t ascsize = sizeof(mp4asc); + aacenc_mp4asc((aacenc_param_t*)¶ms, aacinfo.confBuf, + aacinfo.confSize, mp4asc, &ascsize); + m4af_set_decoder_specific_info(m4af, 0, mp4asc, ascsize); + } m4af_set_vbr_mode(m4af, 0, params.bitrate_mode); m4af_set_priming_mode(m4af, params.gapless_mode + 1); m4af_begin_write(m4af);