2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
25 #include "wav_reader.h"
31 #define PROGNAME "fdkaac"
34 int read_callback(void *cookie
, void *data
, uint32_t size
)
36 size_t rc
= fread(data
, 1, size
, (FILE*)cookie
);
37 return ferror((FILE*)cookie
) ? -1 : (int)rc
;
41 int write_callback(void *cookie
, const void *data
, uint32_t size
)
43 size_t rc
= fwrite(data
, 1, size
, (FILE*)cookie
);
44 return ferror((FILE*)cookie
) ? -1 : (int)rc
;
48 int seek_callback(void *cookie
, int64_t off
, int whence
)
50 return fseeko((FILE*)cookie
, off
, whence
);
54 int64_t tell_callback(void *cookie
)
56 return ftello((FILE*)cookie
);
64 "Usage: " PROGNAME
" [options] input_file\n"
66 " -h, --help Print this help message\n"
67 " -p, --profile <n> Profile (audio object type)\n"
68 " 2: MPEG-4 AAC LC (default)\n"
69 " 5: MPEG-4 HE-AAC (SBR)\n"
70 " 29: MPEG-4 HE-AAC v2 (SBR+PS)\n"
71 " 23: MPEG-4 AAC LD\n"
72 " 39: MPEG-4 AAC ELD\n"
73 " 129: MPEG-2 AAC LC\n"
74 " 132: MPEG-2 HE-AAC (SBR)\n"
75 " 156: MPEG-2 HE-AAC v2 (SBR+PS)\n"
76 " -b, --bitrate <n> Bitrate in bits per seconds (for CBR)\n"
77 " -m, --bitrate-mode <n> Bitrate configuration\n"
80 " (VBR mode is not officially supported, and\n"
81 " works only on a certain combination of\n"
82 " parameter settings, sample rate, and\n"
83 " channel configuration)\n"
84 " -w, --bandwidth <n> Frequency bandwidth in Hz (AAC LC only)\n"
85 " -a, --afterburner <n> Afterburner\n"
88 " -L, --lowdelay-sbr Enable ELD-SBR (AAC ELD only)\n"
89 " -s, --sbr-signaling <n> SBR signaling mode\n"
90 " 0: Implicit, backward compatible(default)\n"
91 " 1: Explicit SBR and implicit PS\n"
92 " 2: Explicit hierarchical signaling\n"
93 " -f, --transport-format <n> Transport format\n"
94 " 0: RAW (default, muxed into M4A)\n"
99 " 10: LOAS/LATM (LATM within LOAS)\n"
100 " -c, --adts-crc-check Add CRC protection on ADTS header\n"
101 " -h, --header-period <n> StreamMuxConfig/PCE repetition period in\n"
104 " -o <filename> Output filename\n"
105 " --ignore-length Ignore length of WAV header\n"
108 " --title <string>\n"
109 " --artist <string>\n"
110 " --album <string>\n"
111 " --genre <string>\n"
113 " --composer <string>\n"
114 " --grouping <string>\n"
115 " --comment <string>\n"
116 " --album-artist <string>\n"
117 " --track <number[/total]>\n"
118 " --disk <number[/total]>\n"
123 typedef struct aacenc_tag_entry_t
{
126 } aacenc_tag_entry_t
;
128 typedef struct aacenc_param_ex_t
{
131 char *input_filename
;
132 char *output_filename
;
133 unsigned ignore_length
;
135 aacenc_tag_entry_t
*tag_table
;
137 unsigned tag_table_capacity
;
141 int parse_options(int argc
, char **argv
, aacenc_param_ex_t
*params
)
145 aacenc_tag_entry_t
*tag
;
147 static struct option long_options
[] = {
148 { "help", no_argument
, 0, 'h' },
149 { "profile", required_argument
, 0, 'p' },
150 { "bitrate", required_argument
, 0, 'b' },
151 { "biterate-mode", required_argument
, 0, 'm' },
152 { "bandwidth", required_argument
, 0, 'w' },
153 { "afterburner", required_argument
, 0, 'a' },
154 { "lowdelay-sbr", no_argument
, 0, 'L' },
155 { "sbr-signaling", required_argument
, 0, 's' },
156 { "transport-format", required_argument
, 0, 'f' },
157 { "adts-crc-check", no_argument
, 0, 'c' },
158 { "header-period", required_argument
, 0, 'P' },
160 { "ignore-length", no_argument
, 0, 'I' },
162 { "title", required_argument
, 0, M4AF_TAG_TITLE
},
163 { "artist", required_argument
, 0, M4AF_TAG_ARTIST
},
164 { "album", required_argument
, 0, M4AF_TAG_ALBUM
},
165 { "genre", required_argument
, 0, M4AF_TAG_GENRE
},
166 { "date", required_argument
, 0, M4AF_TAG_DATE
},
167 { "composer", required_argument
, 0, M4AF_TAG_COMPOSER
},
168 { "grouping", required_argument
, 0, M4AF_TAG_GROUPING
},
169 { "comment", required_argument
, 0, M4AF_TAG_COMMENT
},
170 { "album-artist", required_argument
, 0, M4AF_TAG_ALBUM_ARTIST
},
171 { "track", required_argument
, 0, M4AF_TAG_TRACK
},
172 { "disk", required_argument
, 0, M4AF_TAG_DISK
},
173 { "tempo", required_argument
, 0, M4AF_TAG_TEMPO
},
175 params
->afterburner
= 1;
177 aacenc_getmainargs(&argc
, &argv
);
178 while ((ch
= getopt_long(argc
, argv
, "hp:b:m:w:a:Ls:f:cP:Io:",
179 long_options
, 0)) != EOF
) {
184 if (sscanf(optarg
, "%u", &n
) != 1) {
185 fprintf(stderr
, "invalid arg for profile\n");
191 if (sscanf(optarg
, "%u", &n
) != 1) {
192 fprintf(stderr
, "invalid arg for bitrate\n");
198 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 5) {
199 fprintf(stderr
, "invalid arg for bitrate-mode\n");
202 params
->bitrate_mode
= n
;
205 if (sscanf(optarg
, "%u", &n
) != 1) {
206 fprintf(stderr
, "invalid arg for bandwidth\n");
209 params
->bandwidth
= n
;
212 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 1) {
213 fprintf(stderr
, "invalid arg for afterburner\n");
216 params
->afterburner
= n
;
219 params
->lowdelay_sbr
= 1;
222 if (sscanf(optarg
, "%u", &n
) != 1 || n
> 2) {
223 fprintf(stderr
, "invalid arg for sbr-signaling\n");
226 params
->sbr_signaling
= n
;
229 if (sscanf(optarg
, "%u", &n
) != 1) {
230 fprintf(stderr
, "invalid arg for transport-format\n");
233 params
->transport_format
= n
;
236 params
->adts_crc_check
= 1;
239 if (sscanf(optarg
, "%u", &n
) != 1) {
240 fprintf(stderr
, "invalid arg for header-period\n");
243 params
->header_period
= n
;
246 params
->output_filename
= optarg
;
249 params
->ignore_length
= 1;
252 case M4AF_TAG_ARTIST
:
256 case M4AF_TAG_COMPOSER
:
257 case M4AF_TAG_GROUPING
:
258 case M4AF_TAG_COMMENT
:
259 case M4AF_TAG_ALBUM_ARTIST
:
263 if (params
->tag_count
== params
->tag_table_capacity
) {
264 unsigned newsize
= params
->tag_table_capacity
;
265 newsize
= newsize
? newsize
* 2 : 1;
267 realloc(params
->tag_table
,
268 newsize
* sizeof(aacenc_tag_entry_t
));
269 params
->tag_table_capacity
= newsize
;
271 tag
= params
->tag_table
+ params
->tag_count
;
282 if (!params
->bitrate
&& !params
->bitrate_mode
) {
283 fprintf(stderr
, "bitrate or bitrate-mode is mandatory\n");
286 if (params
->output_filename
&& !strcmp(params
->output_filename
, "-") &&
287 !params
->transport_format
) {
288 fprintf(stderr
, "stdout streaming is not available on M4A output\n");
291 if (params
->bitrate
&& params
->bitrate
< 10000)
292 params
->bitrate
*= 1000;
293 params
->input_filename
= argv
[optind
];
298 int write_sample(FILE *ofp
, m4af_writer_t
*m4af
,
299 const void *data
, uint32_t size
, uint32_t duration
)
302 fwrite(data
, 1, size
, ofp
);
304 fprintf(stderr
, "ERROR: fwrite(): %s\n", strerror(errno
));
307 } else if (m4af_write_sample(m4af
, 0, data
, size
, duration
) < 0) {
308 fprintf(stderr
, "ERROR: failed to write m4a sample\n");
315 int encode(wav_reader_t
*wavf
, HANDLE_AACENCODER encoder
,
316 uint32_t frame_length
, FILE *ofp
, m4af_writer_t
*m4af
)
320 uint32_t pcmsize
= 0;
327 int frames_written
= 0;
328 aacenc_progress_t progress
= { 0 };
329 const pcm_sample_description_t
*format
= wav_get_format(wavf
);
331 ibuf
= malloc(frame_length
* format
->bytes_per_frame
);
332 aacenc_progress_init(&progress
, wav_get_length(wavf
), format
->sample_rate
);
335 if ((nread
= wav_read_frames(wavf
, ibuf
, frame_length
)) < 0) {
336 fprintf(stderr
, "ERROR: read failed\n");
338 } else if (nread
> 0) {
339 if (pcm_convert_to_native_sint16(format
, ibuf
, nread
,
340 &pcmbuf
, &pcmsize
) < 0) {
341 fprintf(stderr
, "ERROR: unsupported sample format\n");
345 aacenc_progress_update(&progress
, wav_get_position(wavf
),
346 format
->sample_rate
* 2);
348 if ((consumed
= aac_encode_frame(encoder
, format
, pcmbuf
, nread
,
349 &obuf
, &olen
, &osize
)) < 0)
352 if (write_sample(ofp
, m4af
, obuf
, olen
, frame_length
) < 0)
356 } while (nread
> 0 || olen
> 0);
357 aacenc_progress_finish(&progress
, wav_get_position(wavf
));
360 if (ibuf
) free(ibuf
);
361 if (pcmbuf
) free(pcmbuf
);
362 if (obuf
) free(obuf
);
367 int finalize_m4a(m4af_writer_t
*m4af
, const aacenc_param_ex_t
*params
,
368 HANDLE_AACENCODER encoder
)
371 aacenc_tag_entry_t
*tag
= params
->tag_table
;
373 for (i
= 0; i
< params
->tag_count
; ++i
, ++tag
) {
378 if (sscanf(tag
->data
, "%u/%u", &m
, &n
) >= 1)
379 m4af_add_itmf_track_tag(m4af
, m
, n
);
385 if (sscanf(tag
->data
, "%u/%u", &m
, &n
) >= 1)
386 m4af_add_itmf_disk_tag(m4af
, m
, n
);
392 if (sscanf(tag
->data
, "%u", &n
) == 1)
393 m4af_add_itmf_int16_tag(m4af
, tag
->tag
, n
);
398 char *u8
= aacenc_to_utf8(tag
->data
);
399 m4af_add_itmf_string_tag(m4af
, tag
->tag
, u8
);
407 LIB_INFO
*lib_info
= 0;
409 p
+= sprintf(p
, PROGNAME
" %s, ", fdkaac_version
);
411 lib_info
= calloc(FDK_MODULE_LAST
, sizeof(LIB_INFO
));
412 if (aacEncGetLibInfo(lib_info
) == AACENC_OK
) {
413 for (i
= 0; i
< FDK_MODULE_LAST
; ++i
)
414 if (lib_info
[i
].module_id
== FDK_AACENC
)
416 p
+= sprintf(p
, "libfdk-aac %s, ", lib_info
[i
].versionStr
);
419 if (params
->bitrate_mode
)
420 sprintf(p
, "VBR mode %d", params
->bitrate_mode
);
422 sprintf(p
, "CBR %dkbps",
423 aacEncoder_GetParam(encoder
, AACENC_BITRATE
) / 1000);
425 m4af_add_itmf_string_tag(m4af
, M4AF_TAG_TOOL
, tool_info
);
427 if (m4af_finalize(m4af
) < 0) {
428 fprintf(stderr
, "ERROR: failed to finalize m4a\n");
435 const char *basename(const char *filename
)
437 char *p
= strrchr(filename
, '/');
439 char *q
= strrchr(filename
, '\\');
442 return p
? p
+ 1 : filename
;
446 char *generate_output_filename(const char *filename
, const char *ext
)
449 size_t ext_len
= strlen(ext
);
451 if (strcmp(filename
, "-") == 0) {
452 p
= malloc(ext_len
+ 6);
453 sprintf(p
, "stdin%s", ext
);
455 const char *base
= basename(filename
);
456 size_t ilen
= strlen(base
);
457 const char *ext_org
= strrchr(base
, '.');
458 if (ext_org
) ilen
= ext_org
- base
;
459 p
= malloc(ilen
+ ext_len
+ 1);
460 sprintf(p
, "%.*s%s", ilen
, base
, ext
);
465 int main(int argc
, char **argv
)
467 wav_io_context_t wav_io
= { read_callback
, seek_callback
};
468 m4af_io_callbacks_t m4af_io
= {
469 write_callback
, seek_callback
, tell_callback
};
470 aacenc_param_ex_t params
= { 0 };
475 char *output_filename
= 0;
476 wav_reader_t
*wavf
= 0;
477 HANDLE_AACENCODER encoder
= 0;
478 AACENC_InfoStruct aacinfo
= { 0 };
479 m4af_writer_t
*m4af
= 0;
480 const pcm_sample_description_t
*sample_format
;
481 int downsampled_timescale
= 0;
483 struct stat stb
= { 0 };
485 setlocale(LC_CTYPE
, "");
488 if (parse_options(argc
, argv
, ¶ms
) < 0)
491 if ((ifp
= aacenc_fopen(params
.input_filename
, "rb")) == 0) {
492 aacenc_fprintf(stderr
, "ERROR: %s: %s\n", params
.input_filename
,
497 if (fstat(fileno(ifp
), &stb
) == 0 && (stb
.st_mode
& S_IFMT
) != S_IFREG
)
500 if ((wavf
= wav_open(&wav_io
, ifp
, params
.ignore_length
)) == 0) {
501 fprintf(stderr
, "ERROR: broken / unsupported input file\n");
504 sample_format
= wav_get_format(wavf
);
506 if (aacenc_init(&encoder
, (aacenc_param_t
*)¶ms
, sample_format
,
510 if (!params
.output_filename
) {
511 const char *ext
= params
.transport_format
? ".aac" : ".m4a";
512 output_filename
= generate_output_filename(params
.input_filename
, ext
);
513 params
.output_filename
= output_filename
;
516 if ((ofp
= aacenc_fopen(params
.output_filename
, "wb")) == 0) {
517 aacenc_fprintf(stderr
, "ERROR: %s: %s\n", params
.output_filename
,
521 if (!params
.transport_format
) {
523 unsigned framelen
= aacinfo
.frameLength
;
524 int sbr_mode
= aacenc_is_sbr_active((aacenc_param_t
*)¶ms
);
525 int sig_mode
= aacEncoder_GetParam(encoder
, AACENC_SIGNALING_MODE
);
526 if (sbr_mode
&& !sig_mode
)
527 downsampled_timescale
= 1;
528 scale
= sample_format
->sample_rate
>> downsampled_timescale
;
529 if ((m4af
= m4af_create(M4AF_CODEC_MP4A
, scale
, &m4af_io
, ofp
)) < 0)
531 m4af_decoder_specific_info(m4af
, 0, aacinfo
.confBuf
, aacinfo
.confSize
);
532 m4af_set_fixed_frame_duration(m4af
, 0,
533 framelen
>> downsampled_timescale
);
534 m4af_begin_write(m4af
);
536 frame_count
= encode(wavf
, encoder
, aacinfo
.frameLength
, ofp
, m4af
);
540 uint32_t delay
= aacinfo
.encoderDelay
;
541 int64_t frames_read
= wav_get_position(wavf
);
542 uint32_t padding
= frame_count
* aacinfo
.frameLength
543 - frames_read
- aacinfo
.encoderDelay
;
544 m4af_set_priming(m4af
, 0, delay
>> downsampled_timescale
,
545 padding
>> downsampled_timescale
);
546 if (finalize_m4a(m4af
, ¶ms
, encoder
) < 0)
551 if (wavf
) wav_teardown(&wavf
);
552 if (ifp
) fclose(ifp
);
553 if (m4af
) m4af_teardown(&m4af
);
554 if (ofp
) fclose(ofp
);
555 if (encoder
) aacEncClose(&encoder
);
556 if (output_filename
) free(output_filename
);
557 if (params
.tag_table
) free(params
.tag_table
);