mirror of https://git.ffmpeg.org/ffmpeg.git
209 lines
5.1 KiB
C
209 lines
5.1 KiB
C
/*
|
|
* AAC definitions and structures
|
|
* Copyright (c) 2024 Lynne
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
* FFmpeg is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with FFmpeg; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "libavcodec/aactab.h"
|
|
#include "aacdec_ac.h"
|
|
|
|
uint32_t ff_aac_ac_map_process(AACArithState *state, int reset, int N)
|
|
{
|
|
float ratio;
|
|
if (reset) {
|
|
memset(state->last, 0, sizeof(state->last));
|
|
state->last_len = N;
|
|
} else if (state->last_len != N) {
|
|
int i;
|
|
uint8_t last[512 /* 2048 / 4 */];
|
|
memcpy(last, state->last, sizeof(last));
|
|
|
|
ratio = state->last_len / (float)N;
|
|
for (i = 0; i < N/2; i++) {
|
|
int k = (int)(i * ratio);
|
|
state->last[i] = last[k];
|
|
}
|
|
|
|
for (; i < FF_ARRAY_ELEMS(state->last); i++)
|
|
state->last[i] = 0;
|
|
|
|
state->last_len = N;
|
|
}
|
|
|
|
state->cur[3] = 0;
|
|
state->cur[2] = 0;
|
|
state->cur[1] = 0;
|
|
state->cur[0] = 1;
|
|
|
|
state->state_pre = state->last[0] << 12;
|
|
return state->last[0] << 12;
|
|
}
|
|
|
|
uint32_t ff_aac_ac_get_context(AACArithState *state, uint32_t c, int i, int N)
|
|
{
|
|
c = state->state_pre >> 8;
|
|
c = c + (state->last[i + 1] << 8);
|
|
c = (c << 4);
|
|
c += state->cur[1];
|
|
|
|
state->state_pre = c;
|
|
|
|
if (i > 3 &&
|
|
((state->cur[3] + state->cur[2] + state->cur[1]) < 5))
|
|
return c + 0x10000;
|
|
|
|
return c;
|
|
}
|
|
|
|
uint32_t ff_aac_ac_get_pk(uint32_t c)
|
|
{
|
|
int i_min = -1;
|
|
int i, j;
|
|
int i_max = FF_ARRAY_ELEMS(ff_aac_ac_lookup_m) - 1;
|
|
while ((i_max - i_min) > 1) {
|
|
i = i_min + ((i_max - i_min) / 2);
|
|
j = ff_aac_ac_hash_m[i];
|
|
if (c < (j >> 8))
|
|
i_max = i;
|
|
else if (c > (j >> 8))
|
|
i_min = i;
|
|
else
|
|
return (j & 0xFF);
|
|
}
|
|
return ff_aac_ac_lookup_m[i_max];
|
|
}
|
|
|
|
void ff_aac_ac_update_context(AACArithState *state, int idx,
|
|
uint16_t a, uint16_t b)
|
|
{
|
|
state->cur[0] = a + b + 1;
|
|
if (state->cur[0] > 0xF)
|
|
state->cur[0] = 0xF;
|
|
|
|
state->cur[3] = state->cur[2];
|
|
state->cur[2] = state->cur[1];
|
|
state->cur[1] = state->cur[0];
|
|
|
|
state->last[idx] = state->cur[0];
|
|
}
|
|
|
|
/* Initialize AC */
|
|
void ff_aac_ac_init(AACArith *ac, GetBitContext *gb)
|
|
{
|
|
ac->low = 0;
|
|
ac->high = UINT16_MAX;
|
|
ac->val = get_bits(gb, 16);
|
|
}
|
|
|
|
uint16_t ff_aac_ac_decode(AACArith *ac, GetBitContext *gb,
|
|
const uint16_t *cdf, uint16_t cdf_len)
|
|
{
|
|
int val = ac->val;
|
|
int low = ac->low;
|
|
int high = ac->high;
|
|
|
|
int sym;
|
|
int rng = high - low + 1;
|
|
int c = ((((int)(val - low + 1)) << 14) - ((int)1));
|
|
|
|
const uint16_t *p = cdf - 1;
|
|
|
|
/* One for each possible CDF length in the spec */
|
|
switch (cdf_len) {
|
|
case 2:
|
|
if ((p[1] * rng) > c)
|
|
p += 1;
|
|
break;
|
|
case 4:
|
|
if ((p[2] * rng) > c)
|
|
p += 2;
|
|
if ((p[1] * rng) > c)
|
|
p += 1;
|
|
break;
|
|
case 17:
|
|
/* First check if the current probability is even met at all */
|
|
if ((p[1] * rng) <= c)
|
|
break;
|
|
p += 1;
|
|
for (int i = 8; i >= 1; i >>= 1)
|
|
if ((p[i] * rng) > c)
|
|
p += i;
|
|
break;
|
|
case 27:
|
|
if ((p[16] * rng) > c)
|
|
p += 16;
|
|
if ((p[8] * rng) > c)
|
|
p += 8;
|
|
if (p != (cdf - 1 + 24))
|
|
if ((p[4] * rng) > c)
|
|
p += 4;
|
|
if ((p[2] * rng) > c)
|
|
p += 2;
|
|
|
|
if (p != (cdf - 1 + 24 + 2))
|
|
if ((p[1] * rng) > c)
|
|
p += 1;
|
|
break;
|
|
default:
|
|
/* This should never happen */
|
|
av_assert2(0);
|
|
}
|
|
|
|
sym = (int)((ptrdiff_t)(p - cdf)) + 1;
|
|
if (sym)
|
|
high = low + ((rng * cdf[sym - 1]) >> 14) - 1;
|
|
low += (rng * cdf[sym]) >> 14;
|
|
|
|
/* This loop could be done faster */
|
|
while (1) {
|
|
if (high < 32768) {
|
|
;
|
|
} else if (low >= 32768) {
|
|
val -= 32768;
|
|
low -= 32768;
|
|
high -= 32768;
|
|
} else if (low >= 16384 && high < 49152) {
|
|
val -= 16384;
|
|
low -= 16384;
|
|
high -= 16384;
|
|
} else {
|
|
break;
|
|
}
|
|
low += low;
|
|
high += high + 1;
|
|
val = (val << 1) | get_bits1(gb);
|
|
};
|
|
|
|
ac->low = low;
|
|
ac->high = high;
|
|
ac->val = val;
|
|
|
|
return sym;
|
|
}
|
|
|
|
void ff_aac_ac_finish(AACArithState *state, int offset, int N)
|
|
{
|
|
int i;
|
|
|
|
for (i = offset; i < N/2; i++)
|
|
state->last[i] = 1;
|
|
|
|
for (; i < FF_ARRAY_ELEMS(state->last); i++)
|
|
state->last[i] = 0;
|
|
}
|