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