mirror of https://github.com/FFmpeg/FFmpeg.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
7.7 KiB
203 lines
7.7 KiB
/* |
|
* AAC encoder twoloop coder |
|
* Copyright (C) 2008-2009 Konstantin Shishkov |
|
* |
|
* 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 |
|
*/ |
|
|
|
/** |
|
* @file |
|
* AAC encoder twoloop coder |
|
* @author Konstantin Shishkov |
|
*/ |
|
|
|
/** |
|
* This file contains a template for the twoloop coder function. |
|
* It needs to be provided, externally, as an already included declaration, |
|
* the following functions from aacenc_quantization/util.h. They're not included |
|
* explicitly here to make it possible to provide alternative implementations: |
|
* - quantize_band_cost |
|
* - abs_pow34_v |
|
* - find_max_val |
|
* - find_min_book |
|
*/ |
|
|
|
#ifndef AVCODEC_AACCODER_TWOLOOP_H |
|
#define AVCODEC_AACCODER_TWOLOOP_H |
|
|
|
#include <float.h> |
|
#include "libavutil/mathematics.h" |
|
#include "avcodec.h" |
|
#include "put_bits.h" |
|
#include "aac.h" |
|
#include "aacenc.h" |
|
#include "aactab.h" |
|
#include "aacenctab.h" |
|
#include "aac_tablegen_decl.h" |
|
|
|
|
|
/** |
|
* two-loop quantizers search taken from ISO 13818-7 Appendix C |
|
*/ |
|
static void search_for_quantizers_twoloop(AVCodecContext *avctx, |
|
AACEncContext *s, |
|
SingleChannelElement *sce, |
|
const float lambda) |
|
{ |
|
int start = 0, i, w, w2, g; |
|
int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->channels * (lambda / 120.f); |
|
float dists[128] = { 0 }, uplims[128] = { 0 }; |
|
float maxvals[128]; |
|
int fflag, minscaler; |
|
int its = 0; |
|
int allz = 0; |
|
float minthr = INFINITY; |
|
|
|
// for values above this the decoder might end up in an endless loop |
|
// due to always having more bits than what can be encoded. |
|
destbits = FFMIN(destbits, 5800); |
|
//XXX: some heuristic to determine initial quantizers will reduce search time |
|
//determine zero bands and upper limits |
|
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { |
|
for (g = 0; g < sce->ics.num_swb; g++) { |
|
int nz = 0; |
|
float uplim = 0.0f, energy = 0.0f; |
|
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { |
|
FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; |
|
uplim += band->threshold; |
|
energy += band->energy; |
|
if (band->energy <= band->threshold || band->threshold == 0.0f) { |
|
sce->zeroes[(w+w2)*16+g] = 1; |
|
continue; |
|
} |
|
nz = 1; |
|
} |
|
uplims[w*16+g] = uplim *512; |
|
sce->zeroes[w*16+g] = !nz; |
|
if (nz) |
|
minthr = FFMIN(minthr, uplim); |
|
allz |= nz; |
|
} |
|
} |
|
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { |
|
for (g = 0; g < sce->ics.num_swb; g++) { |
|
if (sce->zeroes[w*16+g]) { |
|
sce->sf_idx[w*16+g] = SCALE_ONE_POS; |
|
continue; |
|
} |
|
sce->sf_idx[w*16+g] = SCALE_ONE_POS + FFMIN(log2f(uplims[w*16+g]/minthr)*4,59); |
|
} |
|
} |
|
|
|
if (!allz) |
|
return; |
|
abs_pow34_v(s->scoefs, sce->coeffs, 1024); |
|
|
|
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { |
|
start = w*128; |
|
for (g = 0; g < sce->ics.num_swb; g++) { |
|
const float *scaled = s->scoefs + start; |
|
maxvals[w*16+g] = find_max_val(sce->ics.group_len[w], sce->ics.swb_sizes[g], scaled); |
|
start += sce->ics.swb_sizes[g]; |
|
} |
|
} |
|
|
|
//perform two-loop search |
|
//outer loop - improve quality |
|
do { |
|
int tbits, qstep; |
|
minscaler = sce->sf_idx[0]; |
|
//inner loop - quantize spectrum to fit into given number of bits |
|
qstep = its ? 1 : 32; |
|
do { |
|
int prev = -1; |
|
tbits = 0; |
|
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { |
|
start = w*128; |
|
for (g = 0; g < sce->ics.num_swb; g++) { |
|
const float *coefs = &sce->coeffs[start]; |
|
const float *scaled = &s->scoefs[start]; |
|
int bits = 0; |
|
int cb; |
|
float dist = 0.0f; |
|
|
|
if (sce->zeroes[w*16+g] || sce->sf_idx[w*16+g] >= 218) { |
|
start += sce->ics.swb_sizes[g]; |
|
continue; |
|
} |
|
minscaler = FFMIN(minscaler, sce->sf_idx[w*16+g]); |
|
cb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]); |
|
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { |
|
int b; |
|
dist += quantize_band_cost(s, coefs + w2*128, |
|
scaled + w2*128, |
|
sce->ics.swb_sizes[g], |
|
sce->sf_idx[w*16+g], |
|
cb, |
|
1.0f, |
|
INFINITY, |
|
&b, |
|
0); |
|
bits += b; |
|
} |
|
dists[w*16+g] = dist - bits; |
|
if (prev != -1) { |
|
bits += ff_aac_scalefactor_bits[sce->sf_idx[w*16+g] - prev + SCALE_DIFF_ZERO]; |
|
} |
|
tbits += bits; |
|
start += sce->ics.swb_sizes[g]; |
|
prev = sce->sf_idx[w*16+g]; |
|
} |
|
} |
|
if (tbits > destbits) { |
|
for (i = 0; i < 128; i++) |
|
if (sce->sf_idx[i] < 218 - qstep) |
|
sce->sf_idx[i] += qstep; |
|
} else { |
|
for (i = 0; i < 128; i++) |
|
if (sce->sf_idx[i] > 60 - qstep) |
|
sce->sf_idx[i] -= qstep; |
|
} |
|
qstep >>= 1; |
|
if (!qstep && tbits > destbits*1.02 && sce->sf_idx[0] < 217) |
|
qstep = 1; |
|
} while (qstep); |
|
|
|
fflag = 0; |
|
minscaler = av_clip(minscaler, 60, 255 - SCALE_MAX_DIFF); |
|
|
|
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { |
|
for (g = 0; g < sce->ics.num_swb; g++) { |
|
int prevsc = sce->sf_idx[w*16+g]; |
|
if (dists[w*16+g] > uplims[w*16+g] && sce->sf_idx[w*16+g] > 60) { |
|
if (find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]-1)) |
|
sce->sf_idx[w*16+g]--; |
|
else //Try to make sure there is some energy in every band |
|
sce->sf_idx[w*16+g]-=2; |
|
} |
|
sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], minscaler, minscaler + SCALE_MAX_DIFF); |
|
sce->sf_idx[w*16+g] = FFMIN(sce->sf_idx[w*16+g], 219); |
|
if (sce->sf_idx[w*16+g] != prevsc) |
|
fflag = 1; |
|
sce->band_type[w*16+g] = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]); |
|
} |
|
} |
|
its++; |
|
} while (fflag && its < 10); |
|
} |
|
|
|
#endif /* AVCODEC_AACCODER_TWOLOOP_H */
|
|
|