add --include-sbr-delay
[fdkaac.git] / src / main.c
index 952cfbccc4b91fb92f416992bcdd7326c8b99e6f..5fe46adb791cb5d65dfdeb4266e493d8ab4bbccd 100644 (file)
@@ -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 <n>       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 <n>    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;
@@ -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*)&params, 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*)&params);
     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*)&params);
-        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*)&params, 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, &params, encoder) < 0)
This page took 0.011952 seconds and 4 git commands to generate.