From 9b8f9915c2cac2887e52bb38d263f171b5f7d69d Mon Sep 17 00:00:00 2001 From: nu774 Date: Sun, 27 Oct 2013 19:27:18 +0900 Subject: [PATCH] remove --sbr-signaling Instead, we always use explicit/backward compatible SBR signaling by ASC extension in case of m4a, which is not supported by FDK library (so we do it on our side). For LOAS, we use explicit hierarchical signaling. --- src/aacenc.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/aacenc.h | 4 ++++ src/main.c | 36 ++++++++++++++++-------------- 3 files changed, 86 insertions(+), 17 deletions(-) diff --git a/src/aacenc.c b/src/aacenc.c index af9107d..d25be8a 100644 --- a/src/aacenc.c +++ b/src/aacenc.c @@ -10,6 +10,7 @@ #endif #include #include +#include #include "aacenc.h" int aacenc_is_sbr_active(const aacenc_param_t *params) @@ -25,6 +26,68 @@ int aacenc_is_sbr_active(const aacenc_param_t *params) return 0; } +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]; + + switch (params->profile) { + case AOT_SBR: + case AOT_PS: + 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 << 1) << 3; + if (params->profile == AOT_SBR) { + *outsize = ascsize + 3; + break; + } + 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; + break; + default: + 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 ebb0509..2db945f 100644 --- a/src/aacenc.h +++ b/src/aacenc.h @@ -26,6 +26,10 @@ typedef struct aacenc_param_t { int aacenc_is_sbr_active(const aacenc_param_t *params); +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 952cfbc..9aa72d0 100644 --- a/src/main.c +++ b/src/main.c @@ -133,10 +133,6 @@ PROGNAME " %s\n" " 0: Off\n" " 1: On(default)\n" " -L, --lowdelay-sbr Enable ELD-SBR (AAC ELD only)\n" -" -s, --sbr-signaling SBR signaling mode\n" -" 0: Implicit, backward compatible(default)\n" -" 1: Explicit SBR and implicit PS\n" -" 2: Explicit hierarchical signaling\n" " -f, --transport-format Transport format\n" " 0: RAW (default, muxed into M4A)\n" " 1: ADIF\n" @@ -247,7 +243,6 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params) { "bandwidth", required_argument, 0, 'w' }, { "afterburner", required_argument, 0, 'a' }, { "lowdelay-sbr", no_argument, 0, 'L' }, - { "sbr-signaling", required_argument, 0, 's' }, { "transport-format", required_argument, 0, 'f' }, { "adts-crc-check", no_argument, 0, 'C' }, { "header-period", required_argument, 0, 'P' }, @@ -326,13 +321,6 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params) case 'L': params->lowdelay_sbr = 1; break; - case 's': - if (sscanf(optarg, "%u", &n) != 1 || n > 2) { - fprintf(stderr, "invalid arg for sbr-signaling\n"); - return -1; - } - params->sbr_signaling = n; - break; case 'f': if (sscanf(optarg, "%u", &n) != 1) { fprintf(stderr, "invalid arg for transport-format\n"); @@ -736,6 +724,7 @@ int main(int argc, char **argv) const pcm_sample_description_t *sample_format; int downsampled_timescale = 0; int frame_count = 0; + int sbr_mode = 0; setlocale(LC_CTYPE, ""); setbuf(stderr, 0); @@ -748,6 +737,17 @@ int main(int argc, char **argv) sample_format = pcm_get_format(reader); + /* + * We use explicit/hierarchical signaling for LOAS. + * Other than that, we request implicit signaling to FDK library, then + * append explicit/backward-compatible signaling to ASC in case of MP4FF. + * + * Explicit/backward-compatible signaling of SBR is the most recommended + * way in MPEG4 part3 spec, and seems the only way supported by iTunes. + * Since FDK library does not support it, we have to do it on our side. + */ + params.sbr_signaling = (params.transport_format == TT_MP4_LOAS) ? 2 : 0; + if (aacenc_init(&encoder, (aacenc_param_t*)¶ms, sample_format, &aacinfo) < 0) goto END; @@ -764,19 +764,21 @@ int main(int argc, char **argv) goto END; } handle_signals(); + sbr_mode = aacenc_is_sbr_active((aacenc_param_t*)¶ms); if (!params.transport_format) { uint32_t scale; + uint8_t mp4asc[32]; + uint32_t ascsize = sizeof(mp4asc); unsigned framelen = aacinfo.frameLength; - int sbr_mode = aacenc_is_sbr_active((aacenc_param_t*)¶ms); - int sig_mode = aacEncoder_GetParam(encoder, AACENC_SIGNALING_MODE); - if (sbr_mode && !sig_mode) + if (sbr_mode) downsampled_timescale = 1; scale = sample_format->sample_rate >> downsampled_timescale; if ((m4af = m4af_create(M4AF_CODEC_MP4A, scale, &m4af_io, params.output_fp)) < 0) goto END; - m4af_set_decoder_specific_info(m4af, 0, aacinfo.confBuf, - aacinfo.confSize); + aacenc_mp4asc((aacenc_param_t*)¶ms, aacinfo.confBuf, + aacinfo.confSize, mp4asc, &ascsize); + m4af_set_decoder_specific_info(m4af, 0, mp4asc, ascsize); m4af_set_fixed_frame_duration(m4af, 0, framelen >> downsampled_timescale); m4af_set_vbr_mode(m4af, 0, params.bitrate_mode); -- 2.30.2