mirror of
https://github.com/nu774/fdkaac.git
synced 2025-06-05 23:29:14 +02:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
b159a7b095 | |||
be234dc464 | |||
c9ac59e8d3 | |||
9b8f9915c2 | |||
5ccbfaa710 | |||
8f05e0751b | |||
053279541b | |||
f48bf1294c | |||
8896249ac5 |
22
ChangeLog
22
ChangeLog
@ -1,6 +1,26 @@
|
||||
2013-10-25 nu774 <honeycomb77@gmail.com>
|
||||
|
||||
* update ChangeLog [HEAD]
|
||||
|
||||
* bump version [v0.4.0]
|
||||
|
||||
* update README
|
||||
|
||||
2013-10-24 nu774 <honeycomb77@gmail.com>
|
||||
|
||||
* caf input support
|
||||
|
||||
* refactor pcm io routines
|
||||
|
||||
2013-10-23 nu774 <honeycomb77@gmail.com>
|
||||
|
||||
* cleanup metadata handling
|
||||
|
||||
* --tag-from-json: properly support number/total format in json track field
|
||||
|
||||
2013-10-22 nu774 <honeycomb77@gmail.com>
|
||||
|
||||
* bump version [HEAD]
|
||||
* bump version [v0.3.3]
|
||||
|
||||
* fixed bogus sgpd written on --gapless-mode=1 and 2
|
||||
|
||||
|
63
src/aacenc.c
63
src/aacenc.c
@ -10,6 +10,7 @@
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "aacenc.h"
|
||||
|
||||
int aacenc_is_sbr_active(const aacenc_param_t *params)
|
||||
@ -25,6 +26,68 @@ int aacenc_is_sbr_active(const aacenc_param_t *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const unsigned aacenc_sampling_freq_tab[] = {
|
||||
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
|
||||
16000, 12000, 11025, 8000, 7350, 0, 0, 0
|
||||
};
|
||||
|
||||
static
|
||||
unsigned sampling_freq_index(unsigned rate)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; aacenc_sampling_freq_tab[i]; ++i)
|
||||
if (aacenc_sampling_freq_tab[i] == rate)
|
||||
return i;
|
||||
return 0xf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append backward compatible SBR/PS signaling to implicit signaling ASC,
|
||||
* if SBR/PS is present.
|
||||
*/
|
||||
int aacenc_mp4asc(const aacenc_param_t *params,
|
||||
const uint8_t *asc, uint32_t ascsize,
|
||||
uint8_t *outasc, uint32_t *outsize)
|
||||
{
|
||||
unsigned asc_sfreq = aacenc_sampling_freq_tab[(asc[0]&0x7)<<1 |asc[1]>>7];
|
||||
|
||||
switch (params->profile) {
|
||||
case AOT_SBR:
|
||||
case AOT_PS:
|
||||
if (*outsize < ascsize + 3)
|
||||
return -1;
|
||||
memcpy(outasc, asc, ascsize);
|
||||
/* syncExtensionType:11 (value:0x2b7) */
|
||||
outasc[ascsize+0] = 0x2b << 1;
|
||||
outasc[ascsize+1] = 0x7 << 5;
|
||||
/* extensionAudioObjectType:5 (value:5)*/
|
||||
outasc[ascsize+1] |= 5;
|
||||
/* sbrPresentFlag:1 (value:1) */
|
||||
outasc[ascsize+2] = 0x80;
|
||||
/* extensionSamplingFrequencyIndex:4 */
|
||||
outasc[ascsize+2] |= sampling_freq_index(asc_sfreq << 1) << 3;
|
||||
if (params->profile == AOT_SBR) {
|
||||
*outsize = ascsize + 3;
|
||||
break;
|
||||
}
|
||||
if (*outsize < ascsize + 5)
|
||||
return -1;
|
||||
/* syncExtensionType:11 (value:0x548) */
|
||||
outasc[ascsize+2] |= 0x5;
|
||||
outasc[ascsize+3] = 0x48;
|
||||
/* psPresentFlag:1 (value:1) */
|
||||
outasc[ascsize+4] = 0x80;
|
||||
*outsize = ascsize + 5;
|
||||
break;
|
||||
default:
|
||||
if (*outsize < ascsize)
|
||||
return -1;
|
||||
memcpy(outasc, asc, ascsize);
|
||||
*outsize = ascsize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int aacenc_channel_mode(const pcm_sample_description_t *format)
|
||||
{
|
||||
|
@ -26,6 +26,10 @@ typedef struct aacenc_param_t {
|
||||
|
||||
int aacenc_is_sbr_active(const aacenc_param_t *params);
|
||||
|
||||
int aacenc_mp4asc(const aacenc_param_t *params,
|
||||
const uint8_t *asc, uint32_t ascsize,
|
||||
uint8_t *outasc, uint32_t *outsize);
|
||||
|
||||
int aacenc_init(HANDLE_AACENCODER *encoder, const aacenc_param_t *params,
|
||||
const pcm_sample_description_t *format,
|
||||
AACENC_InfoStruct *info);
|
||||
|
@ -13,8 +13,7 @@
|
||||
#include "lpcm.h"
|
||||
#include "m4af_endian.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define inline __inline
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
# ifdef _M_IX86
|
||||
inline int lrint(double x)
|
||||
{
|
||||
|
59
src/main.c
59
src/main.c
@ -133,10 +133,6 @@ PROGNAME " %s\n"
|
||||
" 0: Off\n"
|
||||
" 1: On(default)\n"
|
||||
" -L, --lowdelay-sbr Enable ELD-SBR (AAC ELD only)\n"
|
||||
" -s, --sbr-signaling <n> SBR signaling mode\n"
|
||||
" 0: Implicit, backward compatible(default)\n"
|
||||
" 1: Explicit SBR and implicit PS\n"
|
||||
" 2: Explicit hierarchical signaling\n"
|
||||
" -f, --transport-format <n> Transport format\n"
|
||||
" 0: RAW (default, muxed into M4A)\n"
|
||||
" 1: ADIF\n"
|
||||
@ -153,7 +149,10 @@ PROGNAME " %s\n"
|
||||
" 0: iTunSMPB (default)\n"
|
||||
" 1: ISO standard (edts + sgpd)\n"
|
||||
" 2: Both\n"
|
||||
" --ignorelength Ignore length of WAV header\n"
|
||||
" --include-sbr-delay Count SBR decoder delay in encoder delay\n"
|
||||
" This is not iTunes compatible, but is default\n"
|
||||
" behavior of FDK library.\n"
|
||||
" -I, --ignorelength Ignore length of WAV header\n"
|
||||
" -S, --silent Don't print progress messages\n"
|
||||
" --moov-before-mdat Place moov box before mdat box on m4a output\n"
|
||||
"\n"
|
||||
@ -208,6 +207,7 @@ typedef struct aacenc_param_ex_t {
|
||||
char *output_filename;
|
||||
FILE *output_fp;
|
||||
unsigned gapless_mode;
|
||||
unsigned include_sbr_delay;
|
||||
unsigned ignore_length;
|
||||
int silent;
|
||||
int moov_before_mdat;
|
||||
@ -230,6 +230,7 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
|
||||
int ch;
|
||||
unsigned n;
|
||||
|
||||
#define OPT_INCLUDE_SBR_DELAY M4AF_FOURCC('s','d','l','y')
|
||||
#define OPT_MOOV_BEFORE_MDAT M4AF_FOURCC('m','o','o','v')
|
||||
#define OPT_RAW_CHANNELS M4AF_FOURCC('r','c','h','n')
|
||||
#define OPT_RAW_RATE M4AF_FOURCC('r','r','a','t')
|
||||
@ -247,12 +248,12 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
|
||||
{ "bandwidth", required_argument, 0, 'w' },
|
||||
{ "afterburner", required_argument, 0, 'a' },
|
||||
{ "lowdelay-sbr", no_argument, 0, 'L' },
|
||||
{ "sbr-signaling", required_argument, 0, 's' },
|
||||
{ "transport-format", required_argument, 0, 'f' },
|
||||
{ "adts-crc-check", no_argument, 0, 'C' },
|
||||
{ "header-period", required_argument, 0, 'P' },
|
||||
|
||||
{ "gapless-mode", required_argument, 0, 'G' },
|
||||
{ "include-sbr-delay", no_argument, 0, OPT_INCLUDE_SBR_DELAY },
|
||||
{ "ignorelength", no_argument, 0, 'I' },
|
||||
{ "silent", no_argument, 0, 'S' },
|
||||
{ "moov-before-mdat", no_argument, 0, OPT_MOOV_BEFORE_MDAT },
|
||||
@ -326,13 +327,6 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
|
||||
case 'L':
|
||||
params->lowdelay_sbr = 1;
|
||||
break;
|
||||
case 's':
|
||||
if (sscanf(optarg, "%u", &n) != 1 || n > 2) {
|
||||
fprintf(stderr, "invalid arg for sbr-signaling\n");
|
||||
return -1;
|
||||
}
|
||||
params->sbr_signaling = n;
|
||||
break;
|
||||
case 'f':
|
||||
if (sscanf(optarg, "%u", &n) != 1) {
|
||||
fprintf(stderr, "invalid arg for transport-format\n");
|
||||
@ -360,6 +354,9 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
|
||||
}
|
||||
params->gapless_mode = n;
|
||||
break;
|
||||
case OPT_INCLUDE_SBR_DELAY:
|
||||
params->include_sbr_delay = 1;
|
||||
break;
|
||||
case 'I':
|
||||
params->ignore_length = 1;
|
||||
break;
|
||||
@ -669,7 +666,7 @@ pcm_reader_t *open_input(aacenc_param_ex_t *params)
|
||||
goto END;
|
||||
}
|
||||
io.cookie = params->input_fp;
|
||||
if (fstat(fileno(io.cookie), &stb) == 0
|
||||
if (fstat(fileno(params->input_fp), &stb) == 0
|
||||
&& (stb.st_mode & S_IFMT) == S_IFREG)
|
||||
io.vtbl = &pcm_io_vtbl;
|
||||
else
|
||||
@ -736,6 +733,7 @@ int main(int argc, char **argv)
|
||||
const pcm_sample_description_t *sample_format;
|
||||
int downsampled_timescale = 0;
|
||||
int frame_count = 0;
|
||||
int sbr_mode = 0;
|
||||
|
||||
setlocale(LC_CTYPE, "");
|
||||
setbuf(stderr, 0);
|
||||
@ -748,6 +746,17 @@ int main(int argc, char **argv)
|
||||
|
||||
sample_format = pcm_get_format(reader);
|
||||
|
||||
/*
|
||||
* We use explicit/hierarchical signaling for LOAS.
|
||||
* Other than that, we request implicit signaling to FDK library, then
|
||||
* append explicit/backward-compatible signaling to ASC in case of MP4FF.
|
||||
*
|
||||
* Explicit/backward-compatible signaling of SBR is the most recommended
|
||||
* way in MPEG4 part3 spec, and seems the only way supported by iTunes.
|
||||
* Since FDK library does not support it, we have to do it on our side.
|
||||
*/
|
||||
params.sbr_signaling = (params.transport_format == TT_MP4_LOAS) ? 2 : 0;
|
||||
|
||||
if (aacenc_init(&encoder, (aacenc_param_t*)¶ms, sample_format,
|
||||
&aacinfo) < 0)
|
||||
goto END;
|
||||
@ -764,19 +773,21 @@ int main(int argc, char **argv)
|
||||
goto END;
|
||||
}
|
||||
handle_signals();
|
||||
sbr_mode = aacenc_is_sbr_active((aacenc_param_t*)¶ms);
|
||||
if (!params.transport_format) {
|
||||
uint32_t scale;
|
||||
uint8_t mp4asc[32];
|
||||
uint32_t ascsize = sizeof(mp4asc);
|
||||
unsigned framelen = aacinfo.frameLength;
|
||||
int sbr_mode = aacenc_is_sbr_active((aacenc_param_t*)¶ms);
|
||||
int sig_mode = aacEncoder_GetParam(encoder, AACENC_SIGNALING_MODE);
|
||||
if (sbr_mode && !sig_mode)
|
||||
if (sbr_mode)
|
||||
downsampled_timescale = 1;
|
||||
scale = sample_format->sample_rate >> downsampled_timescale;
|
||||
if ((m4af = m4af_create(M4AF_CODEC_MP4A, scale, &m4af_io,
|
||||
params.output_fp)) < 0)
|
||||
goto END;
|
||||
m4af_set_decoder_specific_info(m4af, 0, aacinfo.confBuf,
|
||||
aacinfo.confSize);
|
||||
aacenc_mp4asc((aacenc_param_t*)¶ms, aacinfo.confBuf,
|
||||
aacinfo.confSize, mp4asc, &ascsize);
|
||||
m4af_set_decoder_specific_info(m4af, 0, mp4asc, ascsize);
|
||||
m4af_set_fixed_frame_duration(m4af, 0,
|
||||
framelen >> downsampled_timescale);
|
||||
m4af_set_vbr_mode(m4af, 0, params.bitrate_mode);
|
||||
@ -789,9 +800,15 @@ int main(int argc, char **argv)
|
||||
goto END;
|
||||
if (m4af) {
|
||||
uint32_t delay = aacinfo.encoderDelay;
|
||||
uint32_t padding;
|
||||
int64_t frames_read = pcm_get_position(reader);
|
||||
uint32_t padding = frame_count * aacinfo.frameLength
|
||||
- frames_read - aacinfo.encoderDelay;
|
||||
|
||||
if (sbr_mode && params.profile != AOT_ER_AAC_ELD &&
|
||||
!params.include_sbr_delay)
|
||||
delay -= 481 << 1;
|
||||
if (sbr_mode && (delay & 1))
|
||||
++delay;
|
||||
padding = frame_count * aacinfo.frameLength - frames_read - delay;
|
||||
m4af_set_priming(m4af, 0, delay >> downsampled_timescale,
|
||||
padding >> downsampled_timescale);
|
||||
if (finalize_m4a(m4af, ¶ms, encoder) < 0)
|
||||
|
@ -56,7 +56,8 @@ static tag_key_mapping_t tag_mapping_table[] = {
|
||||
{ "grouping", M4AF_TAG_GROUPING },
|
||||
{ "itunescompilation", M4AF_TAG_COMPILATION },
|
||||
{ "lyrics", M4AF_TAG_LYRICS },
|
||||
{ "performer", M4AF_TAG_ARTIST },
|
||||
{ "tempo", M4AF_TAG_TEMPO },
|
||||
{ "recordeddate", M4AF_TAG_DATE },
|
||||
{ "title", M4AF_TAG_TITLE },
|
||||
{ "titlesort", M4AF_FOURCC('s','o','n','m') },
|
||||
{ "titlesortorder", M4AF_FOURCC('s','o','n','m') },
|
||||
|
Reference in New Issue
Block a user