]> iEval git - fdkaac.git/blame_incremental - src/main.c
refactor pcm reader framework
[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" 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 <-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"
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"
150" -C, --adts-crc-check Add CRC protection on ADTS header\n"
151" -h, --header-period <n> StreamMuxConfig/PCE repetition period in\n"
152" transport layer\n"
153"\n"
154" -o <filename> Output filename\n"
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"
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"
162" -I, --ignorelength Ignore length of WAV header\n"
163" -S, --silent Don't print progress messages\n"
164" --moov-before-mdat Place moov box before mdat box on m4a output\n"
165"\n"
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"
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"
193" --tag <fcc>:<value> Set iTunes predefined tag with four char code.\n"
194" --tag-from-file <fcc>:<filename>\n"
195" Same as above, but value is read from file.\n"
196" --long-tag <name>:<value> Set arbitrary tag as iTunes custom metadata.\n"
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"
206 , fdkaac_version);
207}
208
209typedef struct aacenc_param_ex_t {
210 AACENC_PARAMS
211
212 char *input_filename;
213 FILE *input_fp;
214 char *output_filename;
215 FILE *output_fp;
216 unsigned gapless_mode;
217 unsigned include_sbr_delay;
218 unsigned ignore_length;
219 int silent;
220 int moov_before_mdat;
221
222 int is_raw;
223 unsigned raw_channels;
224 unsigned raw_rate;
225 const char *raw_format;
226
227 aacenc_tag_store_t tags;
228 aacenc_tag_store_t source_tags;
229 aacenc_translate_generic_text_tag_ctx_t source_tag_ctx;
230
231 char *json_filename;
232} aacenc_param_ex_t;
233
234static
235int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
236{
237 int ch;
238 int n;
239
240#define OPT_INCLUDE_SBR_DELAY M4AF_FOURCC('s','d','l','y')
241#define OPT_MOOV_BEFORE_MDAT M4AF_FOURCC('m','o','o','v')
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')
248#define OPT_TAG_FROM_JSON M4AF_FOURCC('t','f','j','s')
249
250 static struct option long_options[] = {
251 { "help", no_argument, 0, 'h' },
252 { "profile", required_argument, 0, 'p' },
253 { "bitrate", required_argument, 0, 'b' },
254 { "bitrate-mode", required_argument, 0, 'm' },
255 { "bandwidth", required_argument, 0, 'w' },
256 { "afterburner", required_argument, 0, 'a' },
257 { "lowdelay-sbr", required_argument, 0, 'L' },
258 { "sbr-ratio", required_argument, 0, 's' },
259 { "transport-format", required_argument, 0, 'f' },
260 { "adts-crc-check", no_argument, 0, 'C' },
261 { "header-period", required_argument, 0, 'P' },
262
263 { "gapless-mode", required_argument, 0, 'G' },
264 { "include-sbr-delay", no_argument, 0, OPT_INCLUDE_SBR_DELAY },
265 { "ignorelength", no_argument, 0, 'I' },
266 { "silent", no_argument, 0, 'S' },
267 { "moov-before-mdat", no_argument, 0, OPT_MOOV_BEFORE_MDAT },
268
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 },
286 { "tag", required_argument, 0, OPT_SHORT_TAG },
287 { "tag-from-file", required_argument, 0, OPT_SHORT_TAG_FILE },
288 { "long-tag", required_argument, 0, OPT_LONG_TAG },
289 { "tag-from-json", required_argument, 0, OPT_TAG_FROM_JSON },
290 { 0, 0, 0, 0 },
291 };
292 params->afterburner = 1;
293
294 aacenc_getmainargs(&argc, &argv);
295 while ((ch = getopt_long(argc, argv, "hp:b:m:w:a:Ls:f:CP:G:Io:SR",
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':
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;
348 break;
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;
356 case 'C':
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;
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;
376 case OPT_INCLUDE_SBR_DELAY:
377 params->include_sbr_delay = 1;
378 break;
379 case 'I':
380 params->ignore_length = 1;
381 break;
382 case 'S':
383 params->silent = 1;
384 break;
385 case OPT_MOOV_BEFORE_MDAT:
386 params->moov_before_mdat = 1;
387 break;
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;
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:
420 aacenc_add_tag_to_store(&params->tags, ch, 0, optarg,
421 strlen(optarg), 0);
422 break;
423 case OPT_SHORT_TAG:
424 case OPT_SHORT_TAG_FILE:
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';
436 if (ch == OPT_SHORT_TAG || ch == OPT_SHORT_TAG_FILE) {
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;
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 }
454 aacenc_add_tag_to_store(&params->tags, fcc, optarg,
455 val, strlen(val),
456 ch == OPT_SHORT_TAG_FILE);
457 }
458 break;
459 case OPT_TAG_FROM_JSON:
460 params->json_filename = optarg;
461 break;
462 default:
463 return usage(), -1;
464 }
465 }
466 if (argc == optind)
467 return usage(), -1;
468
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;
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 }
489 params->input_filename = argv[optind];
490 return 0;
491};
492
493static
494int write_sample(FILE *ofp, m4af_ctx_t *m4af, aacenc_frame_t *frame)
495{
496 if (!m4af) {
497 fwrite(frame->data, 1, frame->size, ofp);
498 if (ferror(ofp)) {
499 fprintf(stderr, "ERROR: fwrite(): %s\n", strerror(errno));
500 return -1;
501 }
502 } else if (m4af_write_sample(m4af, 0, frame->data, frame->size, 0) < 0) {
503 fprintf(stderr, "ERROR: failed to write m4a sample\n");
504 return -1;
505 }
506 return 0;
507}
508
509static
510int encode(aacenc_param_ex_t *params, pcm_reader_t *reader,
511 HANDLE_AACENCODER encoder, uint32_t frame_length,
512 m4af_ctx_t *m4af)
513{
514 int16_t *ibuf = 0, *ip;
515 aacenc_frame_t obuf[2] = {{ 0 }}, *obp;
516 unsigned flip = 0;
517 int nread = 1;
518 int rc = -1;
519 int remaining, consumed;
520 int frames_written = 0, encoded = 0;
521 aacenc_progress_t progress = { 0 };
522 const pcm_sample_description_t *fmt = pcm_get_format(reader);
523
524 ibuf = malloc(frame_length * fmt->bytes_per_frame);
525 aacenc_progress_init(&progress, pcm_get_length(reader), fmt->sample_rate);
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 */
532 if (g_interrupted)
533 nread = 0;
534 if (nread > 0) {
535 if ((nread = pcm_read_frames(reader, ibuf, frame_length)) < 0) {
536 fprintf(stderr, "ERROR: read failed\n");
537 goto END;
538 }
539 if (!params->silent)
540 aacenc_progress_update(&progress, pcm_get_position(reader),
541 fmt->sample_rate * 2);
542 }
543 ip = ibuf;
544 remaining = nread;
545 do {
546 obp = &obuf[flip];
547 consumed = aac_encode_frame(encoder, fmt, ip, remaining, obp);
548 if (consumed < 0) goto END;
549 if (consumed == 0 && obp->size == 0) goto DONE;
550 if (obp->size == 0) break;
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];
567 if (write_sample(params->output_fp, m4af, obp) < 0)
568 goto END;
569 ++frames_written;
570 } while (remaining > 0);
571 }
572DONE:
573 if (!params->silent)
574 aacenc_progress_finish(&progress, pcm_get_position(reader));
575 rc = frames_written;
576END:
577 if (ibuf) free(ibuf);
578 if (obuf[0].data) free(obuf[0].data);
579 if (obuf[1].data) free(obuf[1].data);
580 return rc;
581}
582
583static
584void put_tool_tag(m4af_ctx_t *m4af, const aacenc_param_ex_t *params,
585 HANDLE_AACENCODER encoder)
586{
587 char tool_info[256];
588 char *p = tool_info;
589 LIB_INFO lib_info;
590
591 p += sprintf(p, PROGNAME " %s, ", fdkaac_version);
592 aacenc_get_lib_info(&lib_info);
593 p += sprintf(p, "libfdk-aac %s, ", lib_info.versionStr);
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
603static
604int finalize_m4a(m4af_ctx_t *m4af, const aacenc_param_ex_t *params,
605 HANDLE_AACENCODER encoder)
606{
607 unsigned i;
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);
613
614 if (params->json_filename)
615 aacenc_write_tags_from_json(m4af, params->json_filename);
616
617 tag = params->tags.tag_table;
618 for (i = 0; i < params->tags.tag_count; ++i, ++tag)
619 aacenc_write_tag_entry(m4af, tag);
620
621 put_tool_tag(m4af, params, encoder);
622
623 if (m4af_finalize(m4af, params->moov_before_mdat) < 0) {
624 fprintf(stderr, "ERROR: failed to finalize m4a\n");
625 return -1;
626 }
627 return 0;
628}
629
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 {
640 const char *base = aacenc_basename(filename);
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);
645 sprintf(p, "%.*s%s", (int)ilen, base, ext);
646 }
647 return p;
648}
649
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
686static pcm_io_vtbl_t pcm_io_vtbl = {
687 read_callback, seek_callback, tell_callback
688};
689static pcm_io_vtbl_t pcm_io_vtbl_noseek = { read_callback, 0, tell_callback };
690
691static
692pcm_reader_t *open_input(aacenc_param_ex_t *params)
693{
694 pcm_io_context_t io = { 0 };
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 }
703 io.cookie = params->input_fp;
704 if (fstat(fileno(params->input_fp), &stb) == 0
705 && (stb.st_mode & S_IFMT) == S_IFREG)
706 io.vtbl = &pcm_io_vtbl;
707 else
708 io.vtbl = &pcm_io_vtbl_noseek;
709
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;
721 if ((reader = raw_open(&io, &desc)) == 0) {
722 fprintf(stderr, "ERROR: failed to open raw input\n");
723 goto END;
724 }
725 } else {
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:
747 fprintf(stderr, "ERROR: unsupported input file\n");
748 goto END;
749 }
750 }
751 if ((reader = pcm_open_native_converter(reader)) != 0)
752 if ((reader = pcm_open_sint16_converter(reader)) != 0)
753 reader = extrapolater_open(reader);
754 return reader;
755END:
756 return 0;
757}
758
759int main(int argc, char **argv)
760{
761 static m4af_io_callbacks_t m4af_io = {
762 read_callback, write_callback, seek_callback, tell_callback
763 };
764 aacenc_param_ex_t params = { 0 };
765
766 int result = 2;
767 char *output_filename = 0;
768 pcm_reader_t *reader = 0;
769 HANDLE_AACENCODER encoder = 0;
770 AACENC_InfoStruct aacinfo = { 0 };
771 m4af_ctx_t *m4af = 0;
772 const pcm_sample_description_t *sample_format;
773 int frame_count = 0;
774 int sbr_mode = 0;
775 unsigned scale_shift = 0;
776
777 setlocale(LC_CTYPE, "");
778 setbuf(stderr, 0);
779
780 if (parse_options(argc, argv, &params) < 0)
781 return 1;
782
783 if ((reader = open_input(&params)) == 0)
784 goto END;
785
786 sample_format = pcm_get_format(reader);
787
788 sbr_mode = aacenc_is_sbr_active((aacenc_param_t*)&params);
789 if (sbr_mode && !aacenc_is_sbr_ratio_available()) {
790 fprintf(stderr, "WARNING: Only dual-rate SBR is available "
791 "for this version\n");
792 params.sbr_ratio = 2;
793 }
794 scale_shift = aacenc_is_dual_rate_sbr((aacenc_param_t*)&params);
795 params.sbr_signaling =
796 (params.transport_format == TT_MP4_LOAS) ? 2 :
797 (params.transport_format == TT_MP4_RAW) ? 1 : 0;
798 if (sbr_mode && !scale_shift)
799 params.sbr_signaling = 2;
800
801 if (aacenc_init(&encoder, (aacenc_param_t*)&params, sample_format,
802 &aacinfo) < 0)
803 goto END;
804
805 if (!params.output_filename) {
806 const char *ext = params.transport_format ? ".aac" : ".m4a";
807 output_filename = generate_output_filename(params.input_filename, ext);
808 params.output_filename = output_filename;
809 }
810
811 if ((params.output_fp = aacenc_fopen(params.output_filename, "wb+")) == 0) {
812 aacenc_fprintf(stderr, "ERROR: %s: %s\n", params.output_filename,
813 strerror(errno));
814 goto END;
815 }
816 handle_signals();
817
818 if (!params.transport_format) {
819 uint32_t scale;
820 unsigned framelen = aacinfo.frameLength;
821 scale = sample_format->sample_rate >> scale_shift;
822 if ((m4af = m4af_create(M4AF_CODEC_MP4A, scale, &m4af_io,
823 params.output_fp)) < 0)
824 goto END;
825 m4af_set_decoder_specific_info(m4af, 0,
826 aacinfo.confBuf, aacinfo.confSize);
827 m4af_set_fixed_frame_duration(m4af, 0, framelen >> scale_shift);
828 m4af_set_vbr_mode(m4af, 0, params.bitrate_mode);
829 m4af_set_priming_mode(m4af, params.gapless_mode + 1);
830 m4af_begin_write(m4af);
831 }
832 if (scale_shift && (aacinfo.encoderDelay & 1)) {
833 /*
834 * Since odd delay cannot be exactly expressed in downsampled scale,
835 * we push one zero frame to the encoder here, to make delay even
836 */
837 int16_t zero[8] = { 0 };
838 aacenc_frame_t frame = { 0 };
839 aac_encode_frame(encoder, sample_format, zero, 1, &frame);
840 free(frame.data);
841 }
842 frame_count = encode(&params, reader, encoder, aacinfo.frameLength, m4af);
843 if (frame_count < 0)
844 goto END;
845 if (m4af) {
846 uint32_t delay = aacinfo.encoderDelay;
847 uint32_t padding;
848 int64_t frames_read = pcm_get_position(reader);
849
850 if (sbr_mode && params.profile != AOT_ER_AAC_ELD &&
851 !params.include_sbr_delay)
852 delay -= 481 << scale_shift;
853 if (scale_shift && (delay & 1))
854 ++delay;
855 padding = frame_count * aacinfo.frameLength - frames_read - delay;
856 m4af_set_priming(m4af, 0, delay >> scale_shift, padding >> scale_shift);
857 if (finalize_m4a(m4af, &params, encoder) < 0)
858 goto END;
859 }
860 result = 0;
861END:
862 if (reader) pcm_teardown(&reader);
863 if (params.input_fp) fclose(params.input_fp);
864 if (m4af) m4af_teardown(&m4af);
865 if (params.output_fp) fclose(params.output_fp);
866 if (encoder) aacEncClose(&encoder);
867 if (output_filename) free(output_filename);
868 if (params.tags.tag_table)
869 aacenc_free_tag_store(&params.tags);
870 if (params.source_tags.tag_table)
871 aacenc_free_tag_store(&params.source_tags);
872
873 return result;
874}
This page took 0.030576 seconds and 4 git commands to generate.