prepend 1 sample zero padding in case of SBR and enc_delay is odd
[fdkaac.git] / src / main.c
... / ...
CommitLineData
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#if HAVE_INTTYPES_H
12# include <inttypes.h>
13#elif defined(_MSC_VER)
14# define SCNd64 "I64d"
15#endif
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <ctype.h>
20#include <locale.h>
21#include <errno.h>
22#include <sys/stat.h>
23#include <getopt.h>
24#if HAVE_UNISTD_H
25#include <unistd.h>
26#endif
27#if HAVE_SIGACTION
28#include <signal.h>
29#endif
30#ifdef _WIN32
31#include <io.h>
32#define WIN32_LEAN_AND_MEAN
33#include <windows.h>
34#endif
35#include "compat.h"
36#include "wav_reader.h"
37#include "caf_reader.h"
38#include "aacenc.h"
39#include "m4af.h"
40#include "progress.h"
41#include "version.h"
42#include "metadata.h"
43
44#define PROGNAME "fdkaac"
45
46static volatile int g_interrupted = 0;
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
80static
81int read_callback(void *cookie, void *data, uint32_t size)
82{
83 size_t rc = fread(data, 1, size, (FILE*)cookie);
84 return ferror((FILE*)cookie) ? -1 : (int)rc;
85}
86
87static
88int write_callback(void *cookie, const void *data, uint32_t size)
89{
90 size_t rc = fwrite(data, 1, size, (FILE*)cookie);
91 return ferror((FILE*)cookie) ? -1 : (int)rc;
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"
132" -a, --afterburner <n> Afterburner\n"
133" 0: Off\n"
134" 1: On(default)\n"
135" -L, --lowdelay-sbr Enable ELD-SBR (AAC ELD only)\n"
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"
143" -C, --adts-crc-check Add CRC protection on ADTS header\n"
144" -h, --header-period <n> StreamMuxConfig/PCE repetition period in\n"
145" transport layer\n"
146"\n"
147" -o <filename> Output filename\n"
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"
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"
155" -I, --ignorelength Ignore length of WAV header\n"
156" -S, --silent Don't print progress messages\n"
157" --moov-before-mdat Place moov box before mdat box on m4a output\n"
158"\n"
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"
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"
186" --tag <fcc>:<value> Set iTunes predefined tag with four char code.\n"
187" --tag-from-file <fcc>:<filename>\n"
188" Same as above, but value is read from file.\n"
189" --long-tag <name>:<value> Set arbitrary tag as iTunes custom metadata.\n"
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"
199 , fdkaac_version);
200}
201
202typedef struct aacenc_param_ex_t {
203 AACENC_PARAMS
204
205 char *input_filename;
206 FILE *input_fp;
207 char *output_filename;
208 FILE *output_fp;
209 unsigned gapless_mode;
210 unsigned include_sbr_delay;
211 unsigned ignore_length;
212 int silent;
213 int moov_before_mdat;
214
215 int is_raw;
216 unsigned raw_channels;
217 unsigned raw_rate;
218 const char *raw_format;
219
220 aacenc_tag_store_t tags;
221 aacenc_tag_store_t source_tags;
222 aacenc_translate_generic_text_tag_ctx_t source_tag_ctx;
223
224 char *json_filename;
225} aacenc_param_ex_t;
226
227static
228int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
229{
230 int ch;
231 unsigned n;
232
233#define OPT_INCLUDE_SBR_DELAY M4AF_FOURCC('s','d','l','y')
234#define OPT_MOOV_BEFORE_MDAT M4AF_FOURCC('m','o','o','v')
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')
241#define OPT_TAG_FROM_JSON M4AF_FOURCC('t','f','j','s')
242
243 static struct option long_options[] = {
244 { "help", no_argument, 0, 'h' },
245 { "profile", required_argument, 0, 'p' },
246 { "bitrate", required_argument, 0, 'b' },
247 { "bitrate-mode", required_argument, 0, 'm' },
248 { "bandwidth", required_argument, 0, 'w' },
249 { "afterburner", required_argument, 0, 'a' },
250 { "lowdelay-sbr", no_argument, 0, 'L' },
251 { "transport-format", required_argument, 0, 'f' },
252 { "adts-crc-check", no_argument, 0, 'C' },
253 { "header-period", required_argument, 0, 'P' },
254
255 { "gapless-mode", required_argument, 0, 'G' },
256 { "include-sbr-delay", no_argument, 0, OPT_INCLUDE_SBR_DELAY },
257 { "ignorelength", no_argument, 0, 'I' },
258 { "silent", no_argument, 0, 'S' },
259 { "moov-before-mdat", no_argument, 0, OPT_MOOV_BEFORE_MDAT },
260
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 },
278 { "tag", required_argument, 0, OPT_SHORT_TAG },
279 { "tag-from-file", required_argument, 0, OPT_SHORT_TAG_FILE },
280 { "long-tag", required_argument, 0, OPT_LONG_TAG },
281 { "tag-from-json", required_argument, 0, OPT_TAG_FROM_JSON },
282 { 0, 0, 0, 0 },
283 };
284 params->afterburner = 1;
285
286 aacenc_getmainargs(&argc, &argv);
287 while ((ch = getopt_long(argc, argv, "hp:b:m:w:a:Ls:f:CP:G:Io:SR",
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;
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;
337 case 'C':
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;
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;
357 case OPT_INCLUDE_SBR_DELAY:
358 params->include_sbr_delay = 1;
359 break;
360 case 'I':
361 params->ignore_length = 1;
362 break;
363 case 'S':
364 params->silent = 1;
365 break;
366 case OPT_MOOV_BEFORE_MDAT:
367 params->moov_before_mdat = 1;
368 break;
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;
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:
401 aacenc_add_tag_to_store(&params->tags, ch, 0, optarg,
402 strlen(optarg), 0);
403 break;
404 case OPT_SHORT_TAG:
405 case OPT_SHORT_TAG_FILE:
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';
417 if (ch == OPT_SHORT_TAG || ch == OPT_SHORT_TAG_FILE) {
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;
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 }
435 aacenc_add_tag_to_store(&params->tags, fcc, optarg,
436 val, strlen(val),
437 ch == OPT_SHORT_TAG_FILE);
438 }
439 break;
440 case OPT_TAG_FROM_JSON:
441 params->json_filename = optarg;
442 break;
443 default:
444 return usage(), -1;
445 }
446 }
447 if (argc == optind)
448 return usage(), -1;
449
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;
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 }
470 params->input_filename = argv[optind];
471 return 0;
472};
473
474static
475int write_sample(FILE *ofp, m4af_ctx_t *m4af,
476 const void *data, uint32_t size, uint32_t duration)
477{
478 if (!m4af) {
479 fwrite(data, 1, size, ofp);
480 if (ferror(ofp)) {
481 fprintf(stderr, "ERROR: fwrite(): %s\n", strerror(errno));
482 return -1;
483 }
484 } else if (m4af_write_sample(m4af, 0, data, size, duration) < 0) {
485 fprintf(stderr, "ERROR: failed to write m4a sample\n");
486 return -1;
487 }
488 return 0;
489}
490
491static
492int encode(aacenc_param_ex_t *params, pcm_reader_t *reader,
493 HANDLE_AACENCODER encoder, uint32_t frame_length,
494 m4af_ctx_t *m4af)
495{
496 int16_t *ibuf = 0, *ip;
497 aacenc_result_t obuf[2] = {{ 0 }}, *obp;
498 unsigned flip = 0;
499 int nread = 1;
500 int rc = -1;
501 int remaining, consumed;
502 int frames_written = 0, encoded = 0;
503 aacenc_progress_t progress = { 0 };
504 const pcm_sample_description_t *fmt = pcm_get_format(reader);
505
506 ibuf = malloc(frame_length * fmt->bytes_per_frame);
507 aacenc_progress_init(&progress, pcm_get_length(reader), fmt->sample_rate);
508
509 for (;;) {
510 /*
511 * Since we delay the write, we cannot just exit loop when interrupted.
512 * Instead, we regard it as EOF.
513 */
514 if (g_interrupted)
515 nread = 0;
516 if (nread > 0) {
517 if ((nread = pcm_read_frames(reader, ibuf, frame_length)) < 0) {
518 fprintf(stderr, "ERROR: read failed\n");
519 goto END;
520 }
521 if (!params->silent)
522 aacenc_progress_update(&progress, pcm_get_position(reader),
523 fmt->sample_rate * 2);
524 }
525 ip = ibuf;
526 remaining = nread;
527 do {
528 obp = &obuf[flip];
529 consumed = aac_encode_frame(encoder, fmt, ip, remaining, obp);
530 if (consumed < 0) goto END;
531 if (consumed == 0 && obp->len == 0) goto DONE;
532 if (obp->len == 0) break;
533
534 remaining -= consumed;
535 ip += consumed * fmt->channels_per_frame;
536 flip ^= 1;
537 /*
538 * As we pad 1 frame at beginning and ending by our extrapolator,
539 * we want to drop them.
540 * We delay output by 1 frame by double buffering, and discard
541 * second frame and final frame from the encoder.
542 * Since sbr_header is included in the first frame (in case of
543 * SBR), we cannot discard first frame. So we pick second instead.
544 */
545 ++encoded;
546 if (encoded == 1 || encoded == 3)
547 continue;
548 obp = &obuf[flip];
549 if (write_sample(params->output_fp, m4af, obp->data, obp->len,
550 frame_length) < 0)
551 goto END;
552 ++frames_written;
553 } while (remaining > 0);
554 }
555DONE:
556 if (!params->silent)
557 aacenc_progress_finish(&progress, pcm_get_position(reader));
558 rc = frames_written;
559END:
560 if (ibuf) free(ibuf);
561 if (obuf[0].data) free(obuf[0].data);
562 if (obuf[1].data) free(obuf[1].data);
563 return rc;
564}
565
566static
567void put_tool_tag(m4af_ctx_t *m4af, const aacenc_param_ex_t *params,
568 HANDLE_AACENCODER encoder)
569{
570 char tool_info[256];
571 char *p = tool_info;
572 LIB_INFO *lib_info = 0;
573
574 p += sprintf(p, PROGNAME " %s, ", fdkaac_version);
575
576 lib_info = calloc(FDK_MODULE_LAST, sizeof(LIB_INFO));
577 if (aacEncGetLibInfo(lib_info) == AACENC_OK) {
578 int i;
579 for (i = 0; i < FDK_MODULE_LAST; ++i)
580 if (lib_info[i].module_id == FDK_AACENC)
581 break;
582 p += sprintf(p, "libfdk-aac %s, ", lib_info[i].versionStr);
583 }
584 free(lib_info);
585 if (params->bitrate_mode)
586 sprintf(p, "VBR mode %d", params->bitrate_mode);
587 else
588 sprintf(p, "CBR %dkbps",
589 aacEncoder_GetParam(encoder, AACENC_BITRATE) / 1000);
590
591 m4af_add_itmf_string_tag(m4af, M4AF_TAG_TOOL, tool_info);
592}
593
594static
595int finalize_m4a(m4af_ctx_t *m4af, const aacenc_param_ex_t *params,
596 HANDLE_AACENCODER encoder)
597{
598 unsigned i;
599 aacenc_tag_entry_t *tag;
600
601 tag = params->source_tags.tag_table;
602 for (i = 0; i < params->source_tags.tag_count; ++i, ++tag)
603 aacenc_write_tag_entry(m4af, tag);
604
605 if (params->json_filename)
606 aacenc_write_tags_from_json(m4af, params->json_filename);
607
608 tag = params->tags.tag_table;
609 for (i = 0; i < params->tags.tag_count; ++i, ++tag)
610 aacenc_write_tag_entry(m4af, tag);
611
612 put_tool_tag(m4af, params, encoder);
613
614 if (m4af_finalize(m4af, params->moov_before_mdat) < 0) {
615 fprintf(stderr, "ERROR: failed to finalize m4a\n");
616 return -1;
617 }
618 return 0;
619}
620
621static
622char *generate_output_filename(const char *filename, const char *ext)
623{
624 char *p = 0;
625 size_t ext_len = strlen(ext);
626
627 if (strcmp(filename, "-") == 0) {
628 p = malloc(ext_len + 6);
629 sprintf(p, "stdin%s", ext);
630 } else {
631 const char *base = aacenc_basename(filename);
632 size_t ilen = strlen(base);
633 const char *ext_org = strrchr(base, '.');
634 if (ext_org) ilen = ext_org - base;
635 p = malloc(ilen + ext_len + 1);
636 sprintf(p, "%.*s%s", (int)ilen, base, ext);
637 }
638 return p;
639}
640
641static
642int parse_raw_spec(const char *spec, pcm_sample_description_t *desc)
643{
644 unsigned bits;
645 unsigned char c_type, c_endian = 'L';
646 int type;
647
648 if (sscanf(spec, "%c%u%c", &c_type, &bits, &c_endian) < 2)
649 return -1;
650 c_type = toupper(c_type);
651 c_endian = toupper(c_endian);
652
653 if (c_type == 'S')
654 type = 1;
655 else if (c_type == 'U')
656 type = 2;
657 else if (c_type == 'F')
658 type = 4;
659 else
660 return -1;
661
662 if (c_endian == 'B')
663 type |= 8;
664 else if (c_endian != 'L')
665 return -1;
666
667 if (c_type == 'F' && bits != 32 && bits != 64)
668 return -1;
669 if (c_type != 'F' && (bits < 8 || bits > 32))
670 return -1;
671
672 desc->sample_type = type;
673 desc->bits_per_channel = bits;
674 return 0;
675}
676
677static pcm_io_vtbl_t pcm_io_vtbl = {
678 read_callback, seek_callback, tell_callback
679};
680static pcm_io_vtbl_t pcm_io_vtbl_noseek = { read_callback, 0, 0 };
681
682static
683pcm_reader_t *open_input(aacenc_param_ex_t *params)
684{
685 pcm_io_context_t io = { 0 };
686 pcm_reader_t *reader = 0;
687 struct stat stb = { 0 };
688
689 if ((params->input_fp = aacenc_fopen(params->input_filename, "rb")) == 0) {
690 aacenc_fprintf(stderr, "ERROR: %s: %s\n", params->input_filename,
691 strerror(errno));
692 goto END;
693 }
694 io.cookie = params->input_fp;
695 if (fstat(fileno(params->input_fp), &stb) == 0
696 && (stb.st_mode & S_IFMT) == S_IFREG)
697 io.vtbl = &pcm_io_vtbl;
698 else
699 io.vtbl = &pcm_io_vtbl_noseek;
700
701 if (params->is_raw) {
702 int bytes_per_channel;
703 pcm_sample_description_t desc = { 0 };
704 if (parse_raw_spec(params->raw_format, &desc) < 0) {
705 fprintf(stderr, "ERROR: invalid raw-format spec\n");
706 goto END;
707 }
708 desc.sample_rate = params->raw_rate;
709 desc.channels_per_frame = params->raw_channels;
710 bytes_per_channel = (desc.bits_per_channel + 7) / 8;
711 desc.bytes_per_frame = params->raw_channels * bytes_per_channel;
712 if ((reader = raw_open(&io, &desc)) == 0) {
713 fprintf(stderr, "ERROR: failed to open raw input\n");
714 goto END;
715 }
716 } else {
717 int c;
718 ungetc(c = getc(params->input_fp), params->input_fp);
719
720 switch (c) {
721 case 'R':
722 if ((reader = wav_open(&io, params->ignore_length)) == 0) {
723 fprintf(stderr, "ERROR: broken / unsupported input file\n");
724 goto END;
725 }
726 break;
727 case 'c':
728 params->source_tag_ctx.add = aacenc_add_tag_entry_to_store;
729 params->source_tag_ctx.add_ctx = &params->source_tags;
730 if ((reader = caf_open(&io,
731 aacenc_translate_generic_text_tag,
732 &params->source_tag_ctx)) == 0) {
733 fprintf(stderr, "ERROR: broken / unsupported input file\n");
734 goto END;
735 }
736 break;
737 default:
738 fprintf(stderr, "ERROR: unsupported input file\n");
739 goto END;
740 }
741 }
742 if ((reader = pcm_open_sint16_converter(reader)) != 0)
743 reader = extrapolater_open(reader);
744 return reader;
745END:
746 return 0;
747}
748
749int main(int argc, char **argv)
750{
751 static m4af_io_callbacks_t m4af_io = {
752 read_callback, write_callback, seek_callback, tell_callback
753 };
754 aacenc_param_ex_t params = { 0 };
755
756 int result = 2;
757 char *output_filename = 0;
758 pcm_reader_t *reader = 0;
759 HANDLE_AACENCODER encoder = 0;
760 AACENC_InfoStruct aacinfo = { 0 };
761 m4af_ctx_t *m4af = 0;
762 const pcm_sample_description_t *sample_format;
763 int downsampled_timescale = 0;
764 int frame_count = 0;
765 int sbr_mode = 0;
766
767 setlocale(LC_CTYPE, "");
768 setbuf(stderr, 0);
769
770 if (parse_options(argc, argv, &params) < 0)
771 return 1;
772
773 if ((reader = open_input(&params)) == 0)
774 goto END;
775
776 sample_format = pcm_get_format(reader);
777
778 /*
779 * We use explicit/hierarchical signaling for LOAS.
780 * Other than that, we request implicit signaling to FDK library, then
781 * append explicit/backward-compatible signaling to ASC in case of MP4FF.
782 *
783 * Explicit/backward-compatible signaling of SBR is the most recommended
784 * way in MPEG4 part3 spec, and seems the only way supported by iTunes.
785 * Since FDK library does not support it, we have to do it on our side.
786 */
787 params.sbr_signaling = (params.transport_format == TT_MP4_LOAS) ? 2 : 0;
788
789 if (aacenc_init(&encoder, (aacenc_param_t*)&params, sample_format,
790 &aacinfo) < 0)
791 goto END;
792
793 if (!params.output_filename) {
794 const char *ext = params.transport_format ? ".aac" : ".m4a";
795 output_filename = generate_output_filename(params.input_filename, ext);
796 params.output_filename = output_filename;
797 }
798
799 if ((params.output_fp = aacenc_fopen(params.output_filename, "wb+")) == 0) {
800 aacenc_fprintf(stderr, "ERROR: %s: %s\n", params.output_filename,
801 strerror(errno));
802 goto END;
803 }
804 handle_signals();
805 sbr_mode = aacenc_is_sbr_active((aacenc_param_t*)&params);
806 if (!params.transport_format) {
807 uint32_t scale;
808 uint8_t mp4asc[32];
809 uint32_t ascsize = sizeof(mp4asc);
810 unsigned framelen = aacinfo.frameLength;
811 if (sbr_mode)
812 downsampled_timescale = 1;
813 scale = sample_format->sample_rate >> downsampled_timescale;
814 if ((m4af = m4af_create(M4AF_CODEC_MP4A, scale, &m4af_io,
815 params.output_fp)) < 0)
816 goto END;
817 aacenc_mp4asc((aacenc_param_t*)&params, aacinfo.confBuf,
818 aacinfo.confSize, mp4asc, &ascsize);
819 m4af_set_decoder_specific_info(m4af, 0, mp4asc, ascsize);
820 m4af_set_fixed_frame_duration(m4af, 0,
821 framelen >> downsampled_timescale);
822 m4af_set_vbr_mode(m4af, 0, params.bitrate_mode);
823 m4af_set_priming_mode(m4af, params.gapless_mode + 1);
824 m4af_begin_write(m4af);
825 }
826 if (sbr_mode && (aacinfo.encoderDelay & 1)) {
827 /*
828 * Since odd delay cannot be exactly expressed in downsampled scale,
829 * we push one zero frame to the encoder here, to make delay even
830 */
831 int16_t zero[8] = { 0 };
832 aacenc_result_t obuf = { 0 };
833 aac_encode_frame(encoder, sample_format, zero, 1, &obuf);
834 free(obuf.data);
835 }
836 frame_count = encode(&params, reader, encoder, aacinfo.frameLength, m4af);
837 if (frame_count < 0)
838 goto END;
839 if (m4af) {
840 uint32_t delay = aacinfo.encoderDelay;
841 uint32_t padding;
842 int64_t frames_read = pcm_get_position(reader);
843
844 if (sbr_mode && params.profile != AOT_ER_AAC_ELD &&
845 !params.include_sbr_delay)
846 delay -= 481 << 1;
847 if (sbr_mode && (delay & 1))
848 ++delay;
849 padding = frame_count * aacinfo.frameLength - frames_read - delay;
850 m4af_set_priming(m4af, 0, delay >> downsampled_timescale,
851 padding >> downsampled_timescale);
852 if (finalize_m4a(m4af, &params, encoder) < 0)
853 goto END;
854 }
855 result = 0;
856END:
857 if (reader) pcm_teardown(&reader);
858 if (params.input_fp) fclose(params.input_fp);
859 if (m4af) m4af_teardown(&m4af);
860 if (params.output_fp) fclose(params.output_fp);
861 if (encoder) aacEncClose(&encoder);
862 if (output_filename) free(output_filename);
863 if (params.tags.tag_table)
864 aacenc_free_tag_store(&params.tags);
865 if (params.source_tags.tag_table)
866 aacenc_free_tag_store(&params.source_tags);
867
868 return result;
869}
This page took 0.012302 seconds and 4 git commands to generate.