fix to use libFDKAAC signaling mode 1
[fdkaac.git] / src / aacenc.c
index 65734ab6cdae41c9630159abac079cba3318b03c..a6984fec8a94aa0216a7d02dea358f8879bf2717 100644 (file)
 #endif
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include "aacenc.h"
 
+int aacenc_is_sbr_ratio_available()
+{
+#if AACENCODER_LIB_VL0 < 3 || (AACENCODER_LIB_VL0==3 && AACENCODER_LIB_VL1<4)
+    return 0;
+#else
+    LIB_INFO lib_info;
+    aacenc_get_lib_info(&lib_info);
+    return lib_info.version > 0x03040000;
+#endif
+}
+
 int aacenc_is_sbr_active(const aacenc_param_t *params)
 {
     switch (params->profile) {
@@ -25,15 +37,42 @@ int aacenc_is_sbr_active(const aacenc_param_t *params)
     return 0;
 }
 
+int aacenc_is_dual_rate_sbr(const aacenc_param_t *params)
+{
+    if (params->profile == AOT_PS || params->profile == AOT_MP2_PS)
+        return 1;
+    else if (params->profile == AOT_SBR || params->profile == AOT_MP2_SBR)
+        return params->sbr_ratio == 0 || params->sbr_ratio == 2;
+    else if (params->profile == AOT_ER_AAC_ELD && params->lowdelay_sbr)
+        return params->sbr_ratio == 2;
+    return 0;
+}
+
+void aacenc_get_lib_info(LIB_INFO *info)
+{
+    LIB_INFO *lib_info = 0;
+    lib_info = calloc(FDK_MODULE_LAST, sizeof(LIB_INFO));
+    if (aacEncGetLibInfo(lib_info) == AACENC_OK) {
+        int i;
+        for (i = 0; i < FDK_MODULE_LAST; ++i) {
+            if (lib_info[i].module_id == FDK_AACENC) {
+                memcpy(info, &lib_info[i], sizeof(LIB_INFO));
+                break;
+            }
+        }
+    }
+    free(lib_info);
+}
+
 static
 int aacenc_channel_mode(const pcm_sample_description_t *format)
 {
     uint32_t chanmask = format->channel_mask;
 
-    if (format->channels_per_frame > 6)
+    if (format->channels_per_frame > 8)
         return 0;
     if (!chanmask) {
-        static uint32_t defaults[] = { 0x4, 0x3, 0x7, 0, 0x37, 0x3f };
+        static uint32_t defaults[] = { 0x4, 0x3, 0x7, 0, 0x37, 0x3f, 0, 0x63f };
         chanmask = defaults[format->channels_per_frame - 1];
     }
     switch (chanmask) {
@@ -45,6 +84,10 @@ int aacenc_channel_mode(const pcm_sample_description_t *format)
     case 0x107: return MODE_1_2_1;
     case 0x607: return MODE_1_2_2;
     case 0x60f: return MODE_1_2_2_1;
+#if AACENCODER_LIB_VL0 > 3 || (AACENCODER_LIB_VL0==3 && AACENCODER_LIB_VL1>=4)
+    case 0xff:  return MODE_1_2_2_2_1;
+    case 0x63f: return MODE_7_1_REAR_SURROUND;
+#endif
     }
     return 0;
 }
@@ -55,8 +98,11 @@ int aacenc_init(HANDLE_AACENCODER *encoder, const aacenc_param_t *params,
 {
     int channel_mode;
     int aot;
+    LIB_INFO lib_info;
 
     *encoder = 0;
+    aacenc_get_lib_info(&lib_info);
+
     if ((channel_mode = aacenc_channel_mode(format)) == 0) {
         fprintf(stderr, "ERROR: unsupported channel layout\n");
         goto FAIL;
@@ -82,13 +128,21 @@ int aacenc_init(HANDLE_AACENCODER *encoder, const aacenc_param_t *params,
         fprintf(stderr, "ERROR: unsupported sample rate\n");
         goto FAIL;
     }
-    aacEncoder_SetParam(*encoder, AACENC_CHANNELMODE, channel_mode);
+    if (aacEncoder_SetParam(*encoder, AACENC_CHANNELMODE,
+                            channel_mode) != AACENC_OK) {
+        fprintf(stderr, "ERROR: unsupported channel mode\n");
+        goto FAIL;
+    }
     aacEncoder_SetParam(*encoder, AACENC_BANDWIDTH, params->bandwidth);
     aacEncoder_SetParam(*encoder, AACENC_CHANNELORDER, 1);
     aacEncoder_SetParam(*encoder, AACENC_AFTERBURNER, !!params->afterburner);
 
-    if (aot == AOT_ER_AAC_ELD && params->lowdelay_sbr)
-        aacEncoder_SetParam(*encoder, AACENC_SBR_MODE, 1);
+    aacEncoder_SetParam(*encoder, AACENC_SBR_MODE, params->lowdelay_sbr);
+
+#if AACENCODER_LIB_VL0 > 3 || (AACENCODER_LIB_VL0==3 && AACENCODER_LIB_VL1>=4)
+    if (lib_info.version > 0x03040000)
+        aacEncoder_SetParam(*encoder, AACENC_SBR_RATIO, params->sbr_ratio);
+#endif
 
     if (aacEncoder_SetParam(*encoder, AACENC_TRANSMUX,
                             params->transport_format) != AACENC_OK) {
@@ -97,7 +151,7 @@ int aacenc_init(HANDLE_AACENCODER *encoder, const aacenc_param_t *params,
     }
     if (aacEncoder_SetParam(*encoder, AACENC_SIGNALING_MODE,
                             params->sbr_signaling) != AACENC_OK) {
-        fprintf(stderr, "ERROR: unsupported transport format\n");
+        fprintf(stderr, "ERROR: failed to set SBR signaling mode\n");
         goto FAIL;
     }
     if (params->adts_crc_check)
@@ -124,7 +178,7 @@ FAIL:
 int aac_encode_frame(HANDLE_AACENCODER encoder,
                      const pcm_sample_description_t *format,
                      const int16_t *input, unsigned iframes,
-                     uint8_t **output, uint32_t *olen, uint32_t *osize)
+                     aacenc_frame_t *output)
 {
     uint32_t ilen = iframes * format->channels_per_frame;
     AACENC_BufDesc ibdesc = { 0 }, obdesc = { 0 };
@@ -142,12 +196,14 @@ int aac_encode_frame(HANDLE_AACENCODER encoder,
     unsigned channel_mode, obytes;
 
     channel_mode = aacEncoder_GetParam(encoder, AACENC_CHANNELMODE);
-    obytes = 6144 / 8 * channel_mode + 7;
-    if (!*output || *osize < obytes) {
-        *osize = obytes;
-        *output = realloc(*output, obytes);
+    obytes = 6144 / 8 * channel_mode;
+    if (!output->data || output->capacity < obytes) {
+        uint8_t *p = realloc(output->data, obytes);
+        if (!p) return -1;
+        output->capacity = obytes;
+        output->data = p;
     }
-    obufs[0] = *output;
+    obufs[0] = output->data;
     obuf_sizes[0] = obytes;
 
     iargs.numInSamples = ilen ? ilen : -1; /* -1 for signaling EOF */
@@ -167,6 +223,6 @@ int aac_encode_frame(HANDLE_AACENCODER encoder,
         fprintf(stderr, "ERROR: aacEncEncode() failed\n");
         return -1;
     }
-    *olen = oargs.numOutBytes;
-    return oargs.numInSamples;
+    output->size = oargs.numOutBytes;
+    return oargs.numInSamples / format->channels_per_frame;
 }
This page took 0.012331 seconds and 4 git commands to generate.