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