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