add --sbr-ratio to support AACENC_SBR_RATIO appeared on libFDK 3.4.12
[fdkaac.git] / src / main.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
c5c45908 11#if HAVE_INTTYPES_H
12# include <inttypes.h>
13#elif defined(_MSC_VER)
14# define SCNd64 "I64d"
15#endif
48e2f01c 16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
68543176 19#include <ctype.h>
48e2f01c 20#include <locale.h>
21#include <errno.h>
7222b0b5 22#include <sys/stat.h>
48e2f01c 23#include <getopt.h>
7222b0b5 24#if HAVE_UNISTD_H
25#include <unistd.h>
26#endif
bd3b4b34 27#if HAVE_SIGACTION
28#include <signal.h>
29#endif
7222b0b5 30#ifdef _WIN32
31#include <io.h>
bd3b4b34 32#define WIN32_LEAN_AND_MEAN
33#include <windows.h>
7222b0b5 34#endif
48e2f01c 35#include "compat.h"
36#include "wav_reader.h"
1af8624b 37#include "caf_reader.h"
48e2f01c 38#include "aacenc.h"
39#include "m4af.h"
40#include "progress.h"
41#include "version.h"
cbb23cdb 42#include "metadata.h"
48e2f01c 43
44#define PROGNAME "fdkaac"
45
721d977f 46static volatile int g_interrupted = 0;
bd3b4b34 47
48#if HAVE_SIGACTION
49static void signal_handler(int signum)
50{
51 g_interrupted = 1;
52}
53static void handle_signals(void)
54{
55 int i, sigs[] = { SIGINT, SIGHUP, SIGTERM };
56 for (i = 0; i < sizeof(sigs)/sizeof(sigs[0]); ++i) {
57 struct sigaction sa = { 0 };
58 sa.sa_handler = signal_handler;
59 sa.sa_flags |= SA_RESTART;
60 sigaction(sigs[i], &sa, 0);
61 }
62}
63#elif defined(_WIN32)
64static BOOL WINAPI signal_handler(DWORD type)
65{
66 g_interrupted = 1;
67 return TRUE;
68}
69
70static void handle_signals(void)
71{
72 SetConsoleCtrlHandler(signal_handler, TRUE);
73}
74#else
75static void handle_signals(void)
76{
77}
78#endif
79
48e2f01c 80static
81int read_callback(void *cookie, void *data, uint32_t size)
82{
5e1168a4 83 size_t rc = fread(data, 1, size, (FILE*)cookie);
84 return ferror((FILE*)cookie) ? -1 : (int)rc;
48e2f01c 85}
86
87static
88int write_callback(void *cookie, const void *data, uint32_t size)
89{
5e1168a4 90 size_t rc = fwrite(data, 1, size, (FILE*)cookie);
91 return ferror((FILE*)cookie) ? -1 : (int)rc;
48e2f01c 92}
93
94static
95int seek_callback(void *cookie, int64_t off, int whence)
96{
97 return fseeko((FILE*)cookie, off, whence);
98}
99
100static
101int64_t tell_callback(void *cookie)
102{
103 return ftello((FILE*)cookie);
104}
105
106static
107void usage(void)
108{
109 printf(
110PROGNAME " %s\n"
111"Usage: " PROGNAME " [options] input_file\n"
112"Options:\n"
113" -h, --help Print this help message\n"
114" -p, --profile <n> Profile (audio object type)\n"
115" 2: MPEG-4 AAC LC (default)\n"
116" 5: MPEG-4 HE-AAC (SBR)\n"
117" 29: MPEG-4 HE-AAC v2 (SBR+PS)\n"
118" 23: MPEG-4 AAC LD\n"
119" 39: MPEG-4 AAC ELD\n"
120" 129: MPEG-2 AAC LC\n"
121" 132: MPEG-2 HE-AAC (SBR)\n"
122" 156: MPEG-2 HE-AAC v2 (SBR+PS)\n"
123" -b, --bitrate <n> Bitrate in bits per seconds (for CBR)\n"
124" -m, --bitrate-mode <n> Bitrate configuration\n"
125" 0: CBR (default)\n"
126" 1-5: VBR\n"
127" (VBR mode is not officially supported, and\n"
128" works only on a certain combination of\n"
129" parameter settings, sample rate, and\n"
130" channel configuration)\n"
131" -w, --bandwidth <n> Frequency bandwidth in Hz (AAC LC only)\n"
097ef9a8 132" -a, --afterburner <n> Afterburner\n"
48e2f01c 133" 0: Off\n"
134" 1: On(default)\n"
e1adc178 135" -L, --lowdelay-sbr <-1|0|1> Configure SBR activity on AAC ELD\n"
136" -1: Use ELD SBR auto configurator\n"
137" 0: Disable SBR on ELD (default)\n"
138" 1: Enable SBR on ELD\n"
139" -s, --sbr-ratio <0|1|2> Controls activation of downsampled SBR\n"
140" 0: Use lib default (default)\n"
141" 1: downsampled SBR (default for ELD+SBR)\n"
142" 2: dual-rate SBR (default for HE-AAC)\n"
48e2f01c 143" -f, --transport-format <n> Transport format\n"
144" 0: RAW (default, muxed into M4A)\n"
145" 1: ADIF\n"
146" 2: ADTS\n"
147" 6: LATM MCP=1\n"
148" 7: LATM MCP=0\n"
149" 10: LOAS/LATM (LATM within LOAS)\n"
68543176 150" -C, --adts-crc-check Add CRC protection on ADTS header\n"
48e2f01c 151" -h, --header-period <n> StreamMuxConfig/PCE repetition period in\n"
152" transport layer\n"
153"\n"
154" -o <filename> Output filename\n"
d317e29d 155" -G, --gapless-mode <n> Encoder delay signaling for gapless playback\n"
156" 0: iTunSMPB (default)\n"
157" 1: ISO standard (edts + sgpd)\n"
158" 2: Both\n"
be234dc4 159" --include-sbr-delay Count SBR decoder delay in encoder delay\n"
160" This is not iTunes compatible, but is default\n"
161" behavior of FDK library.\n"
c9ac59e8 162" -I, --ignorelength Ignore length of WAV header\n"
aa2ca1e3 163" -S, --silent Don't print progress messages\n"
fb2b3635 164" --moov-before-mdat Place moov box before mdat box on m4a output\n"
48e2f01c 165"\n"
68543176 166"Options for raw (headerless) input:\n"
167" -R, --raw Treat input as raw (by default WAV is\n"
168" assumed)\n"
169" --raw-channels <n> Number of channels (default: 2)\n"
170" --raw-rate <n> Sample rate (default: 44100)\n"
171" --raw-format <spec> Sample format, default is \"S16L\".\n"
172" Spec is as follows:\n"
173" 1st char: S(igned)|U(nsigned)|F(loat)\n"
174" 2nd part: bits per channel\n"
175" Last char: L(ittle)|B(ig)\n"
176" Last char can be omitted, in which case L is\n"
177" assumed. Spec is case insensitive, therefore\n"
178" \"u16b\" is same as \"U16B\".\n"
179"\n"
48e2f01c 180"Tagging options:\n"
181" --title <string>\n"
182" --artist <string>\n"
183" --album <string>\n"
184" --genre <string>\n"
185" --date <string>\n"
186" --composer <string>\n"
187" --grouping <string>\n"
188" --comment <string>\n"
189" --album-artist <string>\n"
190" --track <number[/total]>\n"
191" --disk <number[/total]>\n"
192" --tempo <n>\n"
c5c45908 193" --tag <fcc>:<value> Set iTunes predefined tag with four char code.\n"
a56831da 194" --tag-from-file <fcc>:<filename>\n"
195" Same as above, but value is read from file.\n"
c5c45908 196" --long-tag <name>:<value> Set arbitrary tag as iTunes custom metadata.\n"
cbb23cdb 197" --tag-from-json <filename[?dot_notation]>\n"
198" Read tags from JSON. By default, tags are\n"
199" assumed to be direct children of the root\n"
200" object(dictionary).\n"
201" Optionally, position of the dictionary\n"
202" that contains tags can be specified with\n"
203" dotted notation.\n"
204" Example:\n"
205" --tag-from-json /path/to/json?format.tags\n"
48e2f01c 206 , fdkaac_version);
207}
208
48e2f01c 209typedef struct aacenc_param_ex_t {
210 AACENC_PARAMS
211
212 char *input_filename;
2d744bd5 213 FILE *input_fp;
48e2f01c 214 char *output_filename;
2d744bd5 215 FILE *output_fp;
d317e29d 216 unsigned gapless_mode;
be234dc4 217 unsigned include_sbr_delay;
48e2f01c 218 unsigned ignore_length;
aa2ca1e3 219 int silent;
fb2b3635 220 int moov_before_mdat;
48e2f01c 221
68543176 222 int is_raw;
223 unsigned raw_channels;
224 unsigned raw_rate;
225 const char *raw_format;
226
3b666b75 227 aacenc_tag_store_t tags;
1af8624b 228 aacenc_tag_store_t source_tags;
229 aacenc_translate_generic_text_tag_ctx_t source_tag_ctx;
48e2f01c 230
cbb23cdb 231 char *json_filename;
232} aacenc_param_ex_t;
c5c45908 233
48e2f01c 234static
235int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
236{
237 int ch;
e1adc178 238 int n;
48e2f01c 239
be234dc4 240#define OPT_INCLUDE_SBR_DELAY M4AF_FOURCC('s','d','l','y')
fb2b3635 241#define OPT_MOOV_BEFORE_MDAT M4AF_FOURCC('m','o','o','v')
a56831da 242#define OPT_RAW_CHANNELS M4AF_FOURCC('r','c','h','n')
243#define OPT_RAW_RATE M4AF_FOURCC('r','r','a','t')
244#define OPT_RAW_FORMAT M4AF_FOURCC('r','f','m','t')
245#define OPT_SHORT_TAG M4AF_FOURCC('s','t','a','g')
246#define OPT_SHORT_TAG_FILE M4AF_FOURCC('s','t','g','f')
247#define OPT_LONG_TAG M4AF_FOURCC('l','t','a','g')
cbb23cdb 248#define OPT_TAG_FROM_JSON M4AF_FOURCC('t','f','j','s')
68543176 249
48e2f01c 250 static struct option long_options[] = {
251 { "help", no_argument, 0, 'h' },
252 { "profile", required_argument, 0, 'p' },
253 { "bitrate", required_argument, 0, 'b' },
34b319e0 254 { "bitrate-mode", required_argument, 0, 'm' },
48e2f01c 255 { "bandwidth", required_argument, 0, 'w' },
256 { "afterburner", required_argument, 0, 'a' },
e1adc178 257 { "lowdelay-sbr", required_argument, 0, 'L' },
258 { "sbr-ratio", required_argument, 0, 's' },
48e2f01c 259 { "transport-format", required_argument, 0, 'f' },
68543176 260 { "adts-crc-check", no_argument, 0, 'C' },
48e2f01c 261 { "header-period", required_argument, 0, 'P' },
262
d317e29d 263 { "gapless-mode", required_argument, 0, 'G' },
be234dc4 264 { "include-sbr-delay", no_argument, 0, OPT_INCLUDE_SBR_DELAY },
5c534696 265 { "ignorelength", no_argument, 0, 'I' },
aa2ca1e3 266 { "silent", no_argument, 0, 'S' },
fb2b3635 267 { "moov-before-mdat", no_argument, 0, OPT_MOOV_BEFORE_MDAT },
48e2f01c 268
68543176 269 { "raw", no_argument, 0, 'R' },
270 { "raw-channels", required_argument, 0, OPT_RAW_CHANNELS },
271 { "raw-rate", required_argument, 0, OPT_RAW_RATE },
272 { "raw-format", required_argument, 0, OPT_RAW_FORMAT },
273
274 { "title", required_argument, 0, M4AF_TAG_TITLE },
275 { "artist", required_argument, 0, M4AF_TAG_ARTIST },
276 { "album", required_argument, 0, M4AF_TAG_ALBUM },
277 { "genre", required_argument, 0, M4AF_TAG_GENRE },
278 { "date", required_argument, 0, M4AF_TAG_DATE },
279 { "composer", required_argument, 0, M4AF_TAG_COMPOSER },
280 { "grouping", required_argument, 0, M4AF_TAG_GROUPING },
281 { "comment", required_argument, 0, M4AF_TAG_COMMENT },
282 { "album-artist", required_argument, 0, M4AF_TAG_ALBUM_ARTIST },
283 { "track", required_argument, 0, M4AF_TAG_TRACK },
284 { "disk", required_argument, 0, M4AF_TAG_DISK },
285 { "tempo", required_argument, 0, M4AF_TAG_TEMPO },
c5c45908 286 { "tag", required_argument, 0, OPT_SHORT_TAG },
a56831da 287 { "tag-from-file", required_argument, 0, OPT_SHORT_TAG_FILE },
c5c45908 288 { "long-tag", required_argument, 0, OPT_LONG_TAG },
cbb23cdb 289 { "tag-from-json", required_argument, 0, OPT_TAG_FROM_JSON },
5c534696 290 { 0, 0, 0, 0 },
48e2f01c 291 };
292 params->afterburner = 1;
293
294 aacenc_getmainargs(&argc, &argv);
d317e29d 295 while ((ch = getopt_long(argc, argv, "hp:b:m:w:a:Ls:f:CP:G:Io:SR",
48e2f01c 296 long_options, 0)) != EOF) {
297 switch (ch) {
298 case 'h':
299 return usage(), -1;
300 case 'p':
301 if (sscanf(optarg, "%u", &n) != 1) {
302 fprintf(stderr, "invalid arg for profile\n");
303 return -1;
304 }
305 params->profile = n;
306 break;
307 case 'b':
308 if (sscanf(optarg, "%u", &n) != 1) {
309 fprintf(stderr, "invalid arg for bitrate\n");
310 return -1;
311 }
312 params->bitrate = n;
313 break;
314 case 'm':
315 if (sscanf(optarg, "%u", &n) != 1 || n > 5) {
316 fprintf(stderr, "invalid arg for bitrate-mode\n");
317 return -1;
318 }
319 params->bitrate_mode = n;
320 break;
321 case 'w':
322 if (sscanf(optarg, "%u", &n) != 1) {
323 fprintf(stderr, "invalid arg for bandwidth\n");
324 return -1;
325 }
326 params->bandwidth = n;
327 break;
328 case 'a':
329 if (sscanf(optarg, "%u", &n) != 1 || n > 1) {
330 fprintf(stderr, "invalid arg for afterburner\n");
331 return -1;
332 }
333 params->afterburner = n;
334 break;
335 case 'L':
e1adc178 336 if (sscanf(optarg, "%d", &n) != 1 || n < -1 || n > 1) {
337 fprintf(stderr, "invalid arg for lowdelay-sbr\n");
338 return -1;
339 }
340 params->lowdelay_sbr = n;
341 break;
342 case 's':
343 if (sscanf(optarg, "%u", &n) != 1 || n > 2) {
344 fprintf(stderr, "invalid arg for sbr-ratio\n");
345 return -1;
346 }
347 params->sbr_ratio = n;
48e2f01c 348 break;
48e2f01c 349 case 'f':
350 if (sscanf(optarg, "%u", &n) != 1) {
351 fprintf(stderr, "invalid arg for transport-format\n");
352 return -1;
353 }
354 params->transport_format = n;
355 break;
229c3ead 356 case 'C':
48e2f01c 357 params->adts_crc_check = 1;
358 break;
359 case 'P':
360 if (sscanf(optarg, "%u", &n) != 1) {
361 fprintf(stderr, "invalid arg for header-period\n");
362 return -1;
363 }
364 params->header_period = n;
365 break;
366 case 'o':
367 params->output_filename = optarg;
368 break;
d317e29d 369 case 'G':
370 if (sscanf(optarg, "%u", &n) != 1 || n > 2) {
371 fprintf(stderr, "invalid arg for gapless-mode\n");
372 return -1;
373 }
374 params->gapless_mode = n;
375 break;
be234dc4 376 case OPT_INCLUDE_SBR_DELAY:
377 params->include_sbr_delay = 1;
378 break;
48e2f01c 379 case 'I':
380 params->ignore_length = 1;
381 break;
aa2ca1e3 382 case 'S':
383 params->silent = 1;
384 break;
fb2b3635 385 case OPT_MOOV_BEFORE_MDAT:
386 params->moov_before_mdat = 1;
387 break;
68543176 388 case 'R':
389 params->is_raw = 1;
390 break;
391 case OPT_RAW_CHANNELS:
392 if (sscanf(optarg, "%u", &n) != 1) {
393 fprintf(stderr, "invalid arg for raw-channels\n");
394 return -1;
395 }
396 params->raw_channels = n;
397 break;
398 case OPT_RAW_RATE:
399 if (sscanf(optarg, "%u", &n) != 1) {
400 fprintf(stderr, "invalid arg for raw-rate\n");
401 return -1;
402 }
403 params->raw_rate = n;
404 break;
405 case OPT_RAW_FORMAT:
406 params->raw_format = optarg;
407 break;
48e2f01c 408 case M4AF_TAG_TITLE:
409 case M4AF_TAG_ARTIST:
410 case M4AF_TAG_ALBUM:
411 case M4AF_TAG_GENRE:
412 case M4AF_TAG_DATE:
413 case M4AF_TAG_COMPOSER:
414 case M4AF_TAG_GROUPING:
415 case M4AF_TAG_COMMENT:
416 case M4AF_TAG_ALBUM_ARTIST:
417 case M4AF_TAG_TRACK:
418 case M4AF_TAG_DISK:
419 case M4AF_TAG_TEMPO:
3b666b75 420 aacenc_add_tag_to_store(&params->tags, ch, 0, optarg,
421 strlen(optarg), 0);
c5c45908 422 break;
423 case OPT_SHORT_TAG:
a56831da 424 case OPT_SHORT_TAG_FILE:
c5c45908 425 case OPT_LONG_TAG:
426 {
427 char *val;
428 size_t klen;
429 unsigned fcc = M4AF_FOURCC('-','-','-','-');
430
431 if ((val = strchr(optarg, ':')) == 0) {
432 fprintf(stderr, "invalid arg for tag\n");
433 return -1;
434 }
435 *val++ = '\0';
a56831da 436 if (ch == OPT_SHORT_TAG || ch == OPT_SHORT_TAG_FILE) {
360cf7dc 437 /*
438 * take care of U+00A9(COPYRIGHT SIGN).
439 * 1) if length of fcc is 3, we prepend '\xa9'.
440 * 2) U+00A9 becomes "\xc2\xa9" in UTF-8. Therefore
441 * we remove first '\xc2'.
442 */
443 if (optarg[0] == '\xc2')
444 ++optarg;
c5c45908 445 if ((klen = strlen(optarg))== 3)
446 fcc = 0xa9;
447 else if (klen != 4) {
448 fprintf(stderr, "invalid arg for tag\n");
449 return -1;
450 }
451 for (; *optarg; ++optarg)
452 fcc = ((fcc << 8) | (*optarg & 0xff));
453 }
3b666b75 454 aacenc_add_tag_to_store(&params->tags, fcc, optarg,
455 val, strlen(val),
456 ch == OPT_SHORT_TAG_FILE);
48e2f01c 457 }
48e2f01c 458 break;
cbb23cdb 459 case OPT_TAG_FROM_JSON:
460 params->json_filename = optarg;
461 break;
48e2f01c 462 default:
463 return usage(), -1;
464 }
465 }
466 if (argc == optind)
467 return usage(), -1;
68543176 468
48e2f01c 469 if (!params->bitrate && !params->bitrate_mode) {
470 fprintf(stderr, "bitrate or bitrate-mode is mandatory\n");
471 return -1;
472 }
473 if (params->output_filename && !strcmp(params->output_filename, "-") &&
474 !params->transport_format) {
475 fprintf(stderr, "stdout streaming is not available on M4A output\n");
476 return -1;
477 }
478 if (params->bitrate && params->bitrate < 10000)
479 params->bitrate *= 1000;
68543176 480
481 if (params->is_raw) {
482 if (!params->raw_channels)
483 params->raw_channels = 2;
484 if (!params->raw_rate)
485 params->raw_rate = 44100;
486 if (!params->raw_format)
487 params->raw_format = "S16L";
488 }
48e2f01c 489 params->input_filename = argv[optind];
490 return 0;
491};
492
493static
d533c8e0 494int write_sample(FILE *ofp, m4af_ctx_t *m4af, aacenc_frame_t *frame)
48e2f01c 495{
496 if (!m4af) {
d533c8e0 497 fwrite(frame->data, 1, frame->size, ofp);
5e1168a4 498 if (ferror(ofp)) {
48e2f01c 499 fprintf(stderr, "ERROR: fwrite(): %s\n", strerror(errno));
500 return -1;
501 }
d533c8e0 502 } else if (m4af_write_sample(m4af, 0, frame->data, frame->size, 0) < 0) {
48e2f01c 503 fprintf(stderr, "ERROR: failed to write m4a sample\n");
504 return -1;
505 }
506 return 0;
507}
508
509static
4d48b091 510int encode(aacenc_param_ex_t *params, pcm_reader_t *reader,
511 HANDLE_AACENCODER encoder, uint32_t frame_length,
512 m4af_ctx_t *m4af)
48e2f01c 513{
4d48b091 514 int16_t *ibuf = 0, *ip;
d533c8e0 515 aacenc_frame_t obuf[2] = {{ 0 }}, *obp;
4d48b091 516 unsigned flip = 0;
48e2f01c 517 int nread = 1;
48e2f01c 518 int rc = -1;
4d48b091 519 int remaining, consumed;
520 int frames_written = 0, encoded = 0;
48e2f01c 521 aacenc_progress_t progress = { 0 };
2d744bd5 522 const pcm_sample_description_t *fmt = pcm_get_format(reader);
48e2f01c 523
2d744bd5 524 ibuf = malloc(frame_length * fmt->bytes_per_frame);
525 aacenc_progress_init(&progress, pcm_get_length(reader), fmt->sample_rate);
4d48b091 526
527 for (;;) {
528 /*
529 * Since we delay the write, we cannot just exit loop when interrupted.
530 * Instead, we regard it as EOF.
531 */
bd3b4b34 532 if (g_interrupted)
533 nread = 0;
4d48b091 534 if (nread > 0) {
2d744bd5 535 if ((nread = pcm_read_frames(reader, ibuf, frame_length)) < 0) {
48e2f01c 536 fprintf(stderr, "ERROR: read failed\n");
537 goto END;
48e2f01c 538 }
4d48b091 539 if (!params->silent)
2d744bd5 540 aacenc_progress_update(&progress, pcm_get_position(reader),
541 fmt->sample_rate * 2);
48e2f01c 542 }
4d48b091 543 ip = ibuf;
544 remaining = nread;
545 do {
546 obp = &obuf[flip];
3b518efd 547 consumed = aac_encode_frame(encoder, fmt, ip, remaining, obp);
4d48b091 548 if (consumed < 0) goto END;
d533c8e0 549 if (consumed == 0 && obp->size == 0) goto DONE;
550 if (obp->size == 0) break;
4d48b091 551
552 remaining -= consumed;
553 ip += consumed * fmt->channels_per_frame;
554 flip ^= 1;
555 /*
556 * As we pad 1 frame at beginning and ending by our extrapolator,
557 * we want to drop them.
558 * We delay output by 1 frame by double buffering, and discard
559 * second frame and final frame from the encoder.
560 * Since sbr_header is included in the first frame (in case of
561 * SBR), we cannot discard first frame. So we pick second instead.
562 */
563 ++encoded;
564 if (encoded == 1 || encoded == 3)
565 continue;
566 obp = &obuf[flip];
d533c8e0 567 if (write_sample(params->output_fp, m4af, obp) < 0)
48e2f01c 568 goto END;
569 ++frames_written;
4d48b091 570 } while (remaining > 0);
571 }
572DONE:
573 if (!params->silent)
2d744bd5 574 aacenc_progress_finish(&progress, pcm_get_position(reader));
48e2f01c 575 rc = frames_written;
576END:
577 if (ibuf) free(ibuf);
4d48b091 578 if (obuf[0].data) free(obuf[0].data);
579 if (obuf[1].data) free(obuf[1].data);
48e2f01c 580 return rc;
581}
582
c5c45908 583static
e4bbeeb0 584void put_tool_tag(m4af_ctx_t *m4af, const aacenc_param_ex_t *params,
c5c45908 585 HANDLE_AACENCODER encoder)
586{
587 char tool_info[256];
588 char *p = tool_info;
e1adc178 589 LIB_INFO lib_info;
c5c45908 590
591 p += sprintf(p, PROGNAME " %s, ", fdkaac_version);
e1adc178 592 aacenc_get_lib_info(&lib_info);
593 p += sprintf(p, "libfdk-aac %s, ", lib_info.versionStr);
c5c45908 594 if (params->bitrate_mode)
595 sprintf(p, "VBR mode %d", params->bitrate_mode);
596 else
597 sprintf(p, "CBR %dkbps",
598 aacEncoder_GetParam(encoder, AACENC_BITRATE) / 1000);
599
600 m4af_add_itmf_string_tag(m4af, M4AF_TAG_TOOL, tool_info);
601}
602
48e2f01c 603static
e4bbeeb0 604int finalize_m4a(m4af_ctx_t *m4af, const aacenc_param_ex_t *params,
48e2f01c 605 HANDLE_AACENCODER encoder)
606{
607 unsigned i;
1af8624b 608 aacenc_tag_entry_t *tag;
609
610 tag = params->source_tags.tag_table;
611 for (i = 0; i < params->source_tags.tag_count; ++i, ++tag)
612 aacenc_write_tag_entry(m4af, tag);
cbb23cdb 613
614 if (params->json_filename)
3b666b75 615 aacenc_write_tags_from_json(m4af, params->json_filename);
cbb23cdb 616
1af8624b 617 tag = params->tags.tag_table;
cbb23cdb 618 for (i = 0; i < params->tags.tag_count; ++i, ++tag)
3b666b75 619 aacenc_write_tag_entry(m4af, tag);
c5c45908 620
621 put_tool_tag(m4af, params, encoder);
48e2f01c 622
fb2b3635 623 if (m4af_finalize(m4af, params->moov_before_mdat) < 0) {
48e2f01c 624 fprintf(stderr, "ERROR: failed to finalize m4a\n");
625 return -1;
626 }
627 return 0;
628}
629
af8fa38d 630static
631char *generate_output_filename(const char *filename, const char *ext)
632{
633 char *p = 0;
634 size_t ext_len = strlen(ext);
635
636 if (strcmp(filename, "-") == 0) {
637 p = malloc(ext_len + 6);
638 sprintf(p, "stdin%s", ext);
639 } else {
5888fddc 640 const char *base = aacenc_basename(filename);
af8fa38d 641 size_t ilen = strlen(base);
642 const char *ext_org = strrchr(base, '.');
643 if (ext_org) ilen = ext_org - base;
644 p = malloc(ilen + ext_len + 1);
6709cf69 645 sprintf(p, "%.*s%s", (int)ilen, base, ext);
af8fa38d 646 }
647 return p;
648}
649
68543176 650static
651int parse_raw_spec(const char *spec, pcm_sample_description_t *desc)
652{
653 unsigned bits;
654 unsigned char c_type, c_endian = 'L';
655 int type;
656
657 if (sscanf(spec, "%c%u%c", &c_type, &bits, &c_endian) < 2)
658 return -1;
659 c_type = toupper(c_type);
660 c_endian = toupper(c_endian);
661
662 if (c_type == 'S')
663 type = 1;
664 else if (c_type == 'U')
665 type = 2;
666 else if (c_type == 'F')
667 type = 4;
668 else
669 return -1;
670
671 if (c_endian == 'B')
672 type |= 8;
673 else if (c_endian != 'L')
674 return -1;
675
676 if (c_type == 'F' && bits != 32 && bits != 64)
677 return -1;
678 if (c_type != 'F' && (bits < 8 || bits > 32))
679 return -1;
680
681 desc->sample_type = type;
682 desc->bits_per_channel = bits;
683 return 0;
684}
685
29a8f73f 686static pcm_io_vtbl_t pcm_io_vtbl = {
687 read_callback, seek_callback, tell_callback
688};
3de0e22d 689static pcm_io_vtbl_t pcm_io_vtbl_noseek = { read_callback, 0, tell_callback };
29a8f73f 690
2d744bd5 691static
692pcm_reader_t *open_input(aacenc_param_ex_t *params)
693{
29a8f73f 694 pcm_io_context_t io = { 0 };
2d744bd5 695 pcm_reader_t *reader = 0;
696 struct stat stb = { 0 };
697
698 if ((params->input_fp = aacenc_fopen(params->input_filename, "rb")) == 0) {
699 aacenc_fprintf(stderr, "ERROR: %s: %s\n", params->input_filename,
700 strerror(errno));
701 goto END;
702 }
29a8f73f 703 io.cookie = params->input_fp;
f48bf129 704 if (fstat(fileno(params->input_fp), &stb) == 0
29a8f73f 705 && (stb.st_mode & S_IFMT) == S_IFREG)
706 io.vtbl = &pcm_io_vtbl;
707 else
708 io.vtbl = &pcm_io_vtbl_noseek;
709
2d744bd5 710 if (params->is_raw) {
711 int bytes_per_channel;
712 pcm_sample_description_t desc = { 0 };
713 if (parse_raw_spec(params->raw_format, &desc) < 0) {
714 fprintf(stderr, "ERROR: invalid raw-format spec\n");
715 goto END;
716 }
717 desc.sample_rate = params->raw_rate;
718 desc.channels_per_frame = params->raw_channels;
719 bytes_per_channel = (desc.bits_per_channel + 7) / 8;
720 desc.bytes_per_frame = params->raw_channels * bytes_per_channel;
29a8f73f 721 if ((reader = raw_open(&io, &desc)) == 0) {
2d744bd5 722 fprintf(stderr, "ERROR: failed to open raw input\n");
723 goto END;
724 }
725 } else {
1af8624b 726 int c;
727 ungetc(c = getc(params->input_fp), params->input_fp);
728
729 switch (c) {
730 case 'R':
731 if ((reader = wav_open(&io, params->ignore_length)) == 0) {
732 fprintf(stderr, "ERROR: broken / unsupported input file\n");
733 goto END;
734 }
735 break;
736 case 'c':
737 params->source_tag_ctx.add = aacenc_add_tag_entry_to_store;
738 params->source_tag_ctx.add_ctx = &params->source_tags;
739 if ((reader = caf_open(&io,
740 aacenc_translate_generic_text_tag,
741 &params->source_tag_ctx)) == 0) {
742 fprintf(stderr, "ERROR: broken / unsupported input file\n");
743 goto END;
744 }
745 break;
746 default:
4d48b091 747 fprintf(stderr, "ERROR: unsupported input file\n");
2d744bd5 748 goto END;
749 }
750 }
4d48b091 751 if ((reader = pcm_open_sint16_converter(reader)) != 0)
752 reader = extrapolater_open(reader);
753 return reader;
2d744bd5 754END:
e8e9f79e 755 return 0;
2d744bd5 756}
757
48e2f01c 758int main(int argc, char **argv)
759{
2d744bd5 760 static m4af_io_callbacks_t m4af_io = {
761 read_callback, write_callback, seek_callback, tell_callback
762 };
48e2f01c 763 aacenc_param_ex_t params = { 0 };
764
765 int result = 2;
48e2f01c 766 char *output_filename = 0;
2d744bd5 767 pcm_reader_t *reader = 0;
48e2f01c 768 HANDLE_AACENCODER encoder = 0;
769 AACENC_InfoStruct aacinfo = { 0 };
e1adc178 770 LIB_INFO lib_info = { 0 };
e4bbeeb0 771 m4af_ctx_t *m4af = 0;
48e2f01c 772 const pcm_sample_description_t *sample_format;
773 int downsampled_timescale = 0;
774 int frame_count = 0;
9b8f9915 775 int sbr_mode = 0;
e1adc178 776 unsigned scale_shift = 0;
48e2f01c 777
778 setlocale(LC_CTYPE, "");
779 setbuf(stderr, 0);
780
781 if (parse_options(argc, argv, &params) < 0)
782 return 1;
783
2d744bd5 784 if ((reader = open_input(&params)) == 0)
48e2f01c 785 goto END;
2d744bd5 786
787 sample_format = pcm_get_format(reader);
48e2f01c 788
9b8f9915 789 /*
790 * We use explicit/hierarchical signaling for LOAS.
791 * Other than that, we request implicit signaling to FDK library, then
792 * append explicit/backward-compatible signaling to ASC in case of MP4FF.
793 *
794 * Explicit/backward-compatible signaling of SBR is the most recommended
795 * way in MPEG4 part3 spec, and seems the only way supported by iTunes.
796 * Since FDK library does not support it, we have to do it on our side.
797 */
e1adc178 798 sbr_mode = aacenc_is_sbr_active((aacenc_param_t*)&params);
799 if (sbr_mode && !aacenc_is_sbr_ratio_available()) {
800 fprintf(stderr, "WARNING: Only dual-rate SBR is available "
801 "for this version\n");
802 params.sbr_ratio = 2;
803 }
804 scale_shift = aacenc_is_dual_rate_sbr((aacenc_param_t*)&params);
9b8f9915 805 params.sbr_signaling = (params.transport_format == TT_MP4_LOAS) ? 2 : 0;
e1adc178 806 if (sbr_mode && !scale_shift)
807 params.sbr_signaling = 2;
9b8f9915 808
48e2f01c 809 if (aacenc_init(&encoder, (aacenc_param_t*)&params, sample_format,
810 &aacinfo) < 0)
811 goto END;
812
813 if (!params.output_filename) {
af8fa38d 814 const char *ext = params.transport_format ? ".aac" : ".m4a";
815 output_filename = generate_output_filename(params.input_filename, ext);
48e2f01c 816 params.output_filename = output_filename;
817 }
818
2d744bd5 819 if ((params.output_fp = aacenc_fopen(params.output_filename, "wb+")) == 0) {
48e2f01c 820 aacenc_fprintf(stderr, "ERROR: %s: %s\n", params.output_filename,
821 strerror(errno));
822 goto END;
823 }
bd3b4b34 824 handle_signals();
e1adc178 825
48e2f01c 826 if (!params.transport_format) {
827 uint32_t scale;
9b8f9915 828 uint8_t mp4asc[32];
829 uint32_t ascsize = sizeof(mp4asc);
48e2f01c 830 unsigned framelen = aacinfo.frameLength;
e1adc178 831 scale = sample_format->sample_rate >> scale_shift;
2d744bd5 832 if ((m4af = m4af_create(M4AF_CODEC_MP4A, scale, &m4af_io,
833 params.output_fp)) < 0)
48e2f01c 834 goto END;
9b8f9915 835 aacenc_mp4asc((aacenc_param_t*)&params, aacinfo.confBuf,
836 aacinfo.confSize, mp4asc, &ascsize);
837 m4af_set_decoder_specific_info(m4af, 0, mp4asc, ascsize);
48e2f01c 838 m4af_set_fixed_frame_duration(m4af, 0,
e1adc178 839 framelen >> scale_shift);
2f6fc566 840 m4af_set_vbr_mode(m4af, 0, params.bitrate_mode);
d317e29d 841 m4af_set_priming_mode(m4af, params.gapless_mode + 1);
48e2f01c 842 m4af_begin_write(m4af);
843 }
e1adc178 844 if (scale_shift && (aacinfo.encoderDelay & 1)) {
c5eec155 845 /*
846 * Since odd delay cannot be exactly expressed in downsampled scale,
847 * we push one zero frame to the encoder here, to make delay even
848 */
849 int16_t zero[8] = { 0 };
d533c8e0 850 aacenc_frame_t frame = { 0 };
851 aac_encode_frame(encoder, sample_format, zero, 1, &frame);
852 free(frame.data);
c5eec155 853 }
4d48b091 854 frame_count = encode(&params, reader, encoder, aacinfo.frameLength, m4af);
48e2f01c 855 if (frame_count < 0)
856 goto END;
857 if (m4af) {
858 uint32_t delay = aacinfo.encoderDelay;
be234dc4 859 uint32_t padding;
2d744bd5 860 int64_t frames_read = pcm_get_position(reader);
be234dc4 861
862 if (sbr_mode && params.profile != AOT_ER_AAC_ELD &&
863 !params.include_sbr_delay)
e1adc178 864 delay -= 481 << scale_shift;
865 if (scale_shift && (delay & 1))
be234dc4 866 ++delay;
867 padding = frame_count * aacinfo.frameLength - frames_read - delay;
e1adc178 868 m4af_set_priming(m4af, 0, delay >> scale_shift, padding >> scale_shift);
48e2f01c 869 if (finalize_m4a(m4af, &params, encoder) < 0)
870 goto END;
871 }
872 result = 0;
873END:
2d744bd5 874 if (reader) pcm_teardown(&reader);
875 if (params.input_fp) fclose(params.input_fp);
48e2f01c 876 if (m4af) m4af_teardown(&m4af);
2d744bd5 877 if (params.output_fp) fclose(params.output_fp);
48e2f01c 878 if (encoder) aacEncClose(&encoder);
879 if (output_filename) free(output_filename);
1af8624b 880 if (params.tags.tag_table)
881 aacenc_free_tag_store(&params.tags);
882 if (params.source_tags.tag_table)
883 aacenc_free_tag_store(&params.source_tags);
48e2f01c 884
885 return result;
886}
This page took 0.072196 seconds and 4 git commands to generate.