add --sbr-ratio to support AACENC_SBR_RATIO appeared on libFDK 3.4.12
[fdkaac.git] / src / aacenc.c
CommitLineData
48e2f01c 1/*
2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
4 */
5#if HAVE_CONFIG_H
6# include "config.h"
7#endif
8#if HAVE_STDINT_H
9# include <stdint.h>
10#endif
11#include <stdio.h>
12#include <stdlib.h>
9b8f9915 13#include <string.h>
48e2f01c 14#include "aacenc.h"
15
e1adc178 16int aacenc_is_sbr_ratio_available()
17{
18#if AACENCODER_LIB_VL0 < 3 || (AACENCODER_LIB_VL0==3 && AACENCODER_LIB_VL1<4)
19 return 0;
20#else
21 LIB_INFO lib_info;
22 aacenc_get_lib_info(&lib_info);
23 return lib_info.version > 0x03040000;
24#endif
25}
26
48e2f01c 27int aacenc_is_sbr_active(const aacenc_param_t *params)
28{
29 switch (params->profile) {
30 case AOT_SBR: case AOT_PS: case AOT_MP2_SBR: case AOT_MP2_PS:
31 case AOT_DABPLUS_SBR: case AOT_DABPLUS_PS:
32 case AOT_DRM_SBR: case AOT_DRM_MPEG_PS:
33 return 1;
34 }
35 if (params->profile == AOT_ER_AAC_ELD && params->lowdelay_sbr)
36 return 1;
37 return 0;
38}
39
e1adc178 40int aacenc_is_dual_rate_sbr(const aacenc_param_t *params)
41{
42 if (params->profile == AOT_PS || params->profile == AOT_MP2_PS)
43 return 1;
44 else if (params->profile == AOT_SBR || params->profile == AOT_MP2_SBR)
45 return params->sbr_ratio == 0 || params->sbr_ratio == 2;
46 else if (params->profile == AOT_ER_AAC_ELD && params->lowdelay_sbr)
47 return params->sbr_ratio == 2;
48 return 0;
49}
50
51void aacenc_get_lib_info(LIB_INFO *info)
52{
53 LIB_INFO *lib_info = 0;
54 lib_info = calloc(FDK_MODULE_LAST, sizeof(LIB_INFO));
55 if (aacEncGetLibInfo(lib_info) == AACENC_OK) {
56 int i;
57 for (i = 0; i < FDK_MODULE_LAST; ++i) {
58 if (lib_info[i].module_id == FDK_AACENC) {
59 memcpy(info, &lib_info[i], sizeof(LIB_INFO));
60 break;
61 }
62 }
63 }
64 free(lib_info);
65}
66
9b8f9915 67static const unsigned aacenc_sampling_freq_tab[] = {
68 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
69 16000, 12000, 11025, 8000, 7350, 0, 0, 0
70};
71
72static
73unsigned sampling_freq_index(unsigned rate)
74{
75 unsigned i;
76 for (i = 0; aacenc_sampling_freq_tab[i]; ++i)
77 if (aacenc_sampling_freq_tab[i] == rate)
78 return i;
79 return 0xf;
80}
81
82/*
83 * Append backward compatible SBR/PS signaling to implicit signaling ASC,
84 * if SBR/PS is present.
85 */
86int aacenc_mp4asc(const aacenc_param_t *params,
87 const uint8_t *asc, uint32_t ascsize,
88 uint8_t *outasc, uint32_t *outsize)
89{
90 unsigned asc_sfreq = aacenc_sampling_freq_tab[(asc[0]&0x7)<<1 |asc[1]>>7];
e1adc178 91 unsigned shift = aacenc_is_dual_rate_sbr(params);
9b8f9915 92
93 switch (params->profile) {
94 case AOT_SBR:
95 case AOT_PS:
e1adc178 96 if (!shift)
97 break;
9b8f9915 98 if (*outsize < ascsize + 3)
99 return -1;
100 memcpy(outasc, asc, ascsize);
101 /* syncExtensionType:11 (value:0x2b7) */
102 outasc[ascsize+0] = 0x2b << 1;
103 outasc[ascsize+1] = 0x7 << 5;
104 /* extensionAudioObjectType:5 (value:5)*/
105 outasc[ascsize+1] |= 5;
106 /* sbrPresentFlag:1 (value:1) */
107 outasc[ascsize+2] = 0x80;
108 /* extensionSamplingFrequencyIndex:4 */
e1adc178 109 outasc[ascsize+2] |= sampling_freq_index(asc_sfreq << shift) << 3;
9b8f9915 110 if (params->profile == AOT_SBR) {
111 *outsize = ascsize + 3;
e1adc178 112 return 0;
9b8f9915 113 }
114 if (*outsize < ascsize + 5)
115 return -1;
116 /* syncExtensionType:11 (value:0x548) */
117 outasc[ascsize+2] |= 0x5;
118 outasc[ascsize+3] = 0x48;
119 /* psPresentFlag:1 (value:1) */
120 outasc[ascsize+4] = 0x80;
121 *outsize = ascsize + 5;
e1adc178 122 return 0;
9b8f9915 123 }
e1adc178 124 if (*outsize < ascsize)
125 return -1;
126 memcpy(outasc, asc, ascsize);
127 *outsize = ascsize;
9b8f9915 128 return 0;
129}
130
48e2f01c 131static
132int aacenc_channel_mode(const pcm_sample_description_t *format)
133{
134 uint32_t chanmask = format->channel_mask;
135
3c0f152d 136 if (format->channels_per_frame > 8)
48e2f01c 137 return 0;
138 if (!chanmask) {
3c0f152d 139 static uint32_t defaults[] = { 0x4, 0x3, 0x7, 0, 0x37, 0x3f, 0, 0x63f };
48e2f01c 140 chanmask = defaults[format->channels_per_frame - 1];
141 }
142 switch (chanmask) {
143 case 0x3: return MODE_2;
144 case 0x4: return MODE_1;
145 case 0x7: return MODE_1_2;
146 case 0x37: return MODE_1_2_2;
147 case 0x3f: return MODE_1_2_2_1;
148 case 0x107: return MODE_1_2_1;
149 case 0x607: return MODE_1_2_2;
150 case 0x60f: return MODE_1_2_2_1;
3c0f152d 151#if AACENCODER_LIB_VL0 > 3 || (AACENCODER_LIB_VL0==3 && AACENCODER_LIB_VL1>=4)
152 case 0xff: return MODE_1_2_2_2_1;
153 case 0x63f: return MODE_7_1_REAR_SURROUND;
154#endif
48e2f01c 155 }
156 return 0;
157}
158
159int aacenc_init(HANDLE_AACENCODER *encoder, const aacenc_param_t *params,
160 const pcm_sample_description_t *format,
161 AACENC_InfoStruct *info)
162{
163 int channel_mode;
164 int aot;
e1adc178 165 LIB_INFO lib_info;
48e2f01c 166
167 *encoder = 0;
e1adc178 168 aacenc_get_lib_info(&lib_info);
169
48e2f01c 170 if ((channel_mode = aacenc_channel_mode(format)) == 0) {
171 fprintf(stderr, "ERROR: unsupported channel layout\n");
172 goto FAIL;
173 }
174 if (aacEncOpen(encoder, 0, 0) != AACENC_OK) {
175 fprintf(stderr, "ERROR: aacEncOpen() failed\n");
176 goto FAIL;
177 }
178 aot = (params->profile ? params->profile : AOT_AAC_LC);
179 if (aacEncoder_SetParam(*encoder, AACENC_AOT, aot) != AACENC_OK) {
180 fprintf(stderr, "ERROR: unsupported profile\n");
181 goto FAIL;
182 }
183 if (params->bitrate_mode == 0)
184 aacEncoder_SetParam(*encoder, AACENC_BITRATE, params->bitrate);
185 else if (aacEncoder_SetParam(*encoder, AACENC_BITRATEMODE,
186 params->bitrate_mode) != AACENC_OK) {
187 fprintf(stderr, "ERROR: unsupported bitrate mode\n");
188 goto FAIL;
189 }
190 if (aacEncoder_SetParam(*encoder, AACENC_SAMPLERATE,
191 format->sample_rate) != AACENC_OK) {
192 fprintf(stderr, "ERROR: unsupported sample rate\n");
193 goto FAIL;
194 }
e1adc178 195 if (aacEncoder_SetParam(*encoder, AACENC_CHANNELMODE,
196 channel_mode) != AACENC_OK) {
197 fprintf(stderr, "ERROR: unsupported channel mode\n");
198 goto FAIL;
199 }
48e2f01c 200 aacEncoder_SetParam(*encoder, AACENC_BANDWIDTH, params->bandwidth);
201 aacEncoder_SetParam(*encoder, AACENC_CHANNELORDER, 1);
202 aacEncoder_SetParam(*encoder, AACENC_AFTERBURNER, !!params->afterburner);
203
e1adc178 204 aacEncoder_SetParam(*encoder, AACENC_SBR_MODE, params->lowdelay_sbr);
205
206#if AACENCODER_LIB_VL0 > 3 || (AACENCODER_LIB_VL0==3 && AACENCODER_LIB_VL1>=4)
207 if (lib_info.version > 0x03040000)
208 aacEncoder_SetParam(*encoder, AACENC_SBR_RATIO, params->sbr_ratio);
209#endif
48e2f01c 210
211 if (aacEncoder_SetParam(*encoder, AACENC_TRANSMUX,
212 params->transport_format) != AACENC_OK) {
213 fprintf(stderr, "ERROR: unsupported transport format\n");
214 goto FAIL;
215 }
216 if (aacEncoder_SetParam(*encoder, AACENC_SIGNALING_MODE,
217 params->sbr_signaling) != AACENC_OK) {
f5363b23 218 fprintf(stderr, "ERROR: failed to set SBR signaling mode\n");
48e2f01c 219 goto FAIL;
220 }
221 if (params->adts_crc_check)
222 aacEncoder_SetParam(*encoder, AACENC_PROTECTION, 1);
223 if (params->header_period)
224 aacEncoder_SetParam(*encoder, AACENC_HEADER_PERIOD,
225 params->header_period);
226
227 if (aacEncEncode(*encoder, 0, 0, 0, 0) != AACENC_OK) {
228 fprintf(stderr, "ERROR: encoder initialization failed\n");
229 goto FAIL;
230 }
231 if (aacEncInfo(*encoder, info) != AACENC_OK) {
232 fprintf(stderr, "ERROR: cannot retrieve encoder info\n");
233 goto FAIL;
234 }
235 return 0;
236FAIL:
237 if (encoder)
238 aacEncClose(encoder);
239 return -1;
240}
241
242int aac_encode_frame(HANDLE_AACENCODER encoder,
243 const pcm_sample_description_t *format,
244 const int16_t *input, unsigned iframes,
d533c8e0 245 aacenc_frame_t *output)
48e2f01c 246{
247 uint32_t ilen = iframes * format->channels_per_frame;
248 AACENC_BufDesc ibdesc = { 0 }, obdesc = { 0 };
249 AACENC_InArgs iargs = { 0 };
250 AACENC_OutArgs oargs = { 0 };
251 void *ibufs[] = { (void*)input };
252 void *obufs[1];
253 INT ibuf_ids[] = { IN_AUDIO_DATA };
254 INT obuf_ids[] = { OUT_BITSTREAM_DATA };
255 INT ibuf_sizes[] = { ilen * sizeof(int16_t) };
256 INT obuf_sizes[1];
257 INT ibuf_el_sizes[] = { sizeof(int16_t) };
258 INT obuf_el_sizes[] = { 1 };
259 AACENC_ERROR err;
260 unsigned channel_mode, obytes;
261
262 channel_mode = aacEncoder_GetParam(encoder, AACENC_CHANNELMODE);
3b518efd 263 obytes = 6144 / 8 * channel_mode;
d533c8e0 264 if (!output->data || output->capacity < obytes) {
3b518efd 265 uint8_t *p = realloc(output->data, obytes);
266 if (!p) return -1;
d533c8e0 267 output->capacity = obytes;
3b518efd 268 output->data = p;
48e2f01c 269 }
3b518efd 270 obufs[0] = output->data;
48e2f01c 271 obuf_sizes[0] = obytes;
272
273 iargs.numInSamples = ilen ? ilen : -1; /* -1 for signaling EOF */
274 ibdesc.numBufs = 1;
275 ibdesc.bufs = ibufs;
276 ibdesc.bufferIdentifiers = ibuf_ids;
277 ibdesc.bufSizes = ibuf_sizes;
278 ibdesc.bufElSizes = ibuf_el_sizes;
279 obdesc.numBufs = 1;
280 obdesc.bufs = obufs;
281 obdesc.bufferIdentifiers = obuf_ids;
282 obdesc.bufSizes = obuf_sizes;
283 obdesc.bufElSizes = obuf_el_sizes;
284
285 err = aacEncEncode(encoder, &ibdesc, &obdesc, &iargs, &oargs);
286 if (err != AACENC_ENCODE_EOF && err != AACENC_OK) {
287 fprintf(stderr, "ERROR: aacEncEncode() failed\n");
288 return -1;
289 }
d533c8e0 290 output->size = oargs.numOutBytes;
4d48b091 291 return oargs.numInSamples / format->channels_per_frame;
48e2f01c 292}
This page took 0.02749 seconds and 4 git commands to generate.