X-Git-Url: http://git.ieval.ro/?a=blobdiff_plain;f=src%2Faacenc.c;h=00c37f333da6b5d5a916326ca428b55f44f80c0f;hb=3c0f152d39a935dbabba2e32db23a6c954f5854f;hp=af9107d32e82630440952d9dbfcd0f8da2757cf7;hpb=f5363b23c3e4f2e2c1ced448e8947fe8f8698e8f;p=fdkaac.git diff --git a/src/aacenc.c b/src/aacenc.c index af9107d..00c37f3 100644 --- a/src/aacenc.c +++ b/src/aacenc.c @@ -10,6 +10,7 @@ #endif #include #include +#include #include "aacenc.h" int aacenc_is_sbr_active(const aacenc_param_t *params) @@ -25,15 +26,77 @@ 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) { uint32_t chanmask = format->channel_mask; - if (format->channels_per_frame > 6) + if (format->channels_per_frame > 8) return 0; if (!chanmask) { - static uint32_t defaults[] = { 0x4, 0x3, 0x7, 0, 0x37, 0x3f }; + static uint32_t defaults[] = { 0x4, 0x3, 0x7, 0, 0x37, 0x3f, 0, 0x63f }; chanmask = defaults[format->channels_per_frame - 1]; } switch (chanmask) { @@ -45,6 +108,10 @@ int aacenc_channel_mode(const pcm_sample_description_t *format) case 0x107: return MODE_1_2_1; case 0x607: return MODE_1_2_2; case 0x60f: return MODE_1_2_2_1; +#if AACENCODER_LIB_VL0 > 3 || (AACENCODER_LIB_VL0==3 && AACENCODER_LIB_VL1>=4) + case 0xff: return MODE_1_2_2_2_1; + case 0x63f: return MODE_7_1_REAR_SURROUND; +#endif } return 0; } @@ -124,7 +191,7 @@ FAIL: int aac_encode_frame(HANDLE_AACENCODER encoder, const pcm_sample_description_t *format, const int16_t *input, unsigned iframes, - uint8_t **output, uint32_t *olen, uint32_t *osize) + aacenc_frame_t *output) { uint32_t ilen = iframes * format->channels_per_frame; AACENC_BufDesc ibdesc = { 0 }, obdesc = { 0 }; @@ -142,12 +209,14 @@ int aac_encode_frame(HANDLE_AACENCODER encoder, unsigned channel_mode, obytes; channel_mode = aacEncoder_GetParam(encoder, AACENC_CHANNELMODE); - obytes = 6144 / 8 * channel_mode + 7; - if (!*output || *osize < obytes) { - *osize = obytes; - *output = realloc(*output, obytes); + obytes = 6144 / 8 * channel_mode; + if (!output->data || output->capacity < obytes) { + uint8_t *p = realloc(output->data, obytes); + if (!p) return -1; + output->capacity = obytes; + output->data = p; } - obufs[0] = *output; + obufs[0] = output->data; obuf_sizes[0] = obytes; iargs.numInSamples = ilen ? ilen : -1; /* -1 for signaling EOF */ @@ -167,6 +236,6 @@ int aac_encode_frame(HANDLE_AACENCODER encoder, fprintf(stderr, "ERROR: aacEncEncode() failed\n"); return -1; } - *olen = oargs.numOutBytes; - return oargs.numInSamples; + output->size = oargs.numOutBytes; + return oargs.numInSamples / format->channels_per_frame; }