X-Git-Url: http://git.ieval.ro/?a=blobdiff_plain;f=src%2Fmain.c;h=5fe46adb791cb5d65dfdeb4266e493d8ab4bbccd;hb=be234dc464159da366ec770fe8e5a958f317f7a9;hp=d8ee02d816f434cf742c6762ce5a64343f800df4;hpb=1af8624b009faf5bc6b9b8dfa76676483da5f6cf;p=fdkaac.git diff --git a/src/main.c b/src/main.c index d8ee02d..5fe46ad 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" @@ -153,7 +149,10 @@ PROGNAME " %s\n" " 0: iTunSMPB (default)\n" " 1: ISO standard (edts + sgpd)\n" " 2: Both\n" -" --ignorelength Ignore length of WAV header\n" +" --include-sbr-delay Count SBR decoder delay in encoder delay\n" +" This is not iTunes compatible, but is default\n" +" behavior of FDK library.\n" +" -I, --ignorelength Ignore length of WAV header\n" " -S, --silent Don't print progress messages\n" " --moov-before-mdat Place moov box before mdat box on m4a output\n" "\n" @@ -208,6 +207,7 @@ typedef struct aacenc_param_ex_t { char *output_filename; FILE *output_fp; unsigned gapless_mode; + unsigned include_sbr_delay; unsigned ignore_length; int silent; int moov_before_mdat; @@ -230,6 +230,7 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params) int ch; unsigned n; +#define OPT_INCLUDE_SBR_DELAY M4AF_FOURCC('s','d','l','y') #define OPT_MOOV_BEFORE_MDAT M4AF_FOURCC('m','o','o','v') #define OPT_RAW_CHANNELS M4AF_FOURCC('r','c','h','n') #define OPT_RAW_RATE M4AF_FOURCC('r','r','a','t') @@ -247,12 +248,12 @@ 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' }, { "gapless-mode", required_argument, 0, 'G' }, + { "include-sbr-delay", no_argument, 0, OPT_INCLUDE_SBR_DELAY }, { "ignorelength", no_argument, 0, 'I' }, { "silent", no_argument, 0, 'S' }, { "moov-before-mdat", no_argument, 0, OPT_MOOV_BEFORE_MDAT }, @@ -326,13 +327,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"); @@ -360,6 +354,9 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params) } params->gapless_mode = n; break; + case OPT_INCLUDE_SBR_DELAY: + params->include_sbr_delay = 1; + break; case 'I': params->ignore_length = 1; break; @@ -669,7 +666,7 @@ pcm_reader_t *open_input(aacenc_param_ex_t *params) goto END; } io.cookie = params->input_fp; - if (fstat(fileno(io.cookie), &stb) == 0 + if (fstat(fileno(params->input_fp), &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFREG) io.vtbl = &pcm_io_vtbl; else @@ -736,6 +733,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 +746,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 +773,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); @@ -789,9 +800,15 @@ int main(int argc, char **argv) goto END; if (m4af) { uint32_t delay = aacinfo.encoderDelay; + uint32_t padding; int64_t frames_read = pcm_get_position(reader); - uint32_t padding = frame_count * aacinfo.frameLength - - frames_read - aacinfo.encoderDelay; + + if (sbr_mode && params.profile != AOT_ER_AAC_ELD && + !params.include_sbr_delay) + delay -= 481 << 1; + if (sbr_mode && (delay & 1)) + ++delay; + padding = frame_count * aacinfo.frameLength - frames_read - delay; m4af_set_priming(m4af, 0, delay >> downsampled_timescale, padding >> downsampled_timescale); if (finalize_m4a(m4af, ¶ms, encoder) < 0)