summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRostislav Pehlivanov <atomnuker@gmail.com>2015-09-05 08:32:09 +0100
committerRostislav Pehlivanov <atomnuker@gmail.com>2015-09-05 08:32:09 +0100
commit4565611b04d53b7333fa5ed81e5dc0074482c20c (patch)
treec407cfc3f504fae4cb08ba47a54deb54a5647312
parenta87ada53c39c983ad20c86983c3bedfd56e7e8eb (diff)
aacenc_is: add a flag to use pure coefficients instead
This commit adds a flag to use the pure coefficients instead of the processed ones (sce->coeffs). This is needed because IS will apply the changes to the coefficients immediately before the adjust_common_prediction function and it doesn't make sense to measure stereo channel coefficient difference when one of the channels coefficients are all zero. Therefore add a flag to use pure coefficients in that case. TNS is the only thing touching the coefficients before IS so common window prediction will not take that into account but the effect of the TNS filter per coefficient can be small (a few percent) so to some approximation it's fine to just ignore that. Also fixed a small error which doesn't alter the results that much. pow(sqrt(number), 3.0/4.0) == pow(number, 3.0/8.0) != pow(number, 3.0/4.0). Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
-rw-r--r--libavcodec/aacenc_is.c36
-rw-r--r--libavcodec/aacenc_is.h3
-rw-r--r--libavcodec/aacenc_pred.c8
3 files changed, 24 insertions, 23 deletions
diff --git a/libavcodec/aacenc_is.c b/libavcodec/aacenc_is.c
index 88ba915d2a..bb201f628d 100644
--- a/libavcodec/aacenc_is.c
+++ b/libavcodec/aacenc_is.c
@@ -32,39 +32,39 @@
struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
int start, int w, int g, float ener0,
- float ener1, float ener01, int phase)
+ float ener1, float ener01,
+ int use_pcoeffs, int phase)
{
int i, w2;
+ SingleChannelElement *sce0 = &cpe->ch[0];
+ SingleChannelElement *sce1 = &cpe->ch[1];
+ float *L = use_pcoeffs ? sce0->pcoeffs : sce0->coeffs;
+ float *R = use_pcoeffs ? sce1->pcoeffs : sce1->coeffs;
float *L34 = &s->scoefs[256*0], *R34 = &s->scoefs[256*1];
float *IS = &s->scoefs[256*2], *I34 = &s->scoefs[256*3];
float dist1 = 0.0f, dist2 = 0.0f;
struct AACISError is_error = {0};
- SingleChannelElement *sce0 = &cpe->ch[0];
- SingleChannelElement *sce1 = &cpe->ch[1];
for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
int is_band_type, is_sf_idx = FFMAX(1, sce0->sf_idx[(w+w2)*16+g]-4);
- float e01_34 = phase*pow(sqrt(ener1/ener0), 3.0/4.0);
+ float e01_34 = phase*pow(ener1/ener0, 3.0/4.0);
float maxval, dist_spec_err = 0.0f;
float minthr = FFMIN(band0->threshold, band1->threshold);
- for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
- IS[i] = (sce0->pcoeffs[start+(w+w2)*128+i]+
- phase*sce1->pcoeffs[start+(w+w2)*128+i])*
- sqrt(ener0/ener01);
- }
- abs_pow34_v(L34, &sce0->coeffs[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
- abs_pow34_v(R34, &sce1->coeffs[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
- abs_pow34_v(I34, IS, sce0->ics.swb_sizes[g]);
+ for (i = 0; i < sce0->ics.swb_sizes[g]; i++)
+ IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01);
+ abs_pow34_v(L34, &L[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
+ abs_pow34_v(R34, &R[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
+ abs_pow34_v(I34, IS, sce0->ics.swb_sizes[g]);
maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34);
is_band_type = find_min_book(maxval, is_sf_idx);
- dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128], L34,
+ dist1 += quantize_band_cost(s, &L[start + (w+w2)*128], L34,
sce0->ics.swb_sizes[g],
sce0->sf_idx[(w+w2)*16+g],
sce0->band_type[(w+w2)*16+g],
s->lambda / band0->threshold, INFINITY, NULL, 0);
- dist1 += quantize_band_cost(s, &sce1->coeffs[start + (w+w2)*128], R34,
+ dist1 += quantize_band_cost(s, &R[start + (w+w2)*128], R34,
sce1->ics.swb_sizes[g],
sce1->sf_idx[(w+w2)*16+g],
sce1->band_type[(w+w2)*16+g],
@@ -111,15 +111,15 @@ void ff_aac_search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElemen
for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
float coef0 = sce0->pcoeffs[start+(w+w2)*128+i];
float coef1 = sce1->pcoeffs[start+(w+w2)*128+i];
- ener0 += coef0*coef0;
- ener1 += coef1*coef1;
+ ener0 += coef0*coef0;
+ ener1 += coef1*coef1;
ener01 += (coef0 + coef1)*(coef0 + coef1);
}
}
ph_err1 = ff_aac_is_encoding_err(s, cpe, start, w, g,
- ener0, ener1, ener01, -1);
+ ener0, ener1, ener01, 0, -1);
ph_err2 = ff_aac_is_encoding_err(s, cpe, start, w, g,
- ener0, ener1, ener01, +1);
+ ener0, ener1, ener01, 0, +1);
erf = ph_err1.error < ph_err2.error ? &ph_err1 : &ph_err2;
if (erf->pass) {
cpe->is_mask[w*16+g] = 1;
diff --git a/libavcodec/aacenc_is.h b/libavcodec/aacenc_is.h
index e35f0aa695..31bbacac58 100644
--- a/libavcodec/aacenc_is.h
+++ b/libavcodec/aacenc_is.h
@@ -43,7 +43,8 @@ struct AACISError {
struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
int start, int w, int g, float ener0,
- float ener1, float ener01, int phase);
+ float ener1, float ener01,
+ int use_pcoeffs, int phase);
void ff_aac_search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe);
#endif /* AVCODEC_AACENC_IS_H */
diff --git a/libavcodec/aacenc_pred.c b/libavcodec/aacenc_pred.c
index fafe0029d4..eb8e7f7d27 100644
--- a/libavcodec/aacenc_pred.c
+++ b/libavcodec/aacenc_pred.c
@@ -179,15 +179,15 @@ void ff_aac_adjust_common_prediction(AACEncContext *s, ChannelElement *cpe)
for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
float coef0 = sce0->pcoeffs[start+(w+w2)*128+i];
float coef1 = sce1->pcoeffs[start+(w+w2)*128+i];
- ener0 += coef0*coef0;
- ener1 += coef1*coef1;
+ ener0 += coef0*coef0;
+ ener1 += coef1*coef1;
ener01 += (coef0 + coef1)*(coef0 + coef1);
}
}
ph_err1 = ff_aac_is_encoding_err(s, cpe, start, w, g,
- ener0, ener1, ener01, -1);
+ ener0, ener1, ener01, 1, -1);
ph_err2 = ff_aac_is_encoding_err(s, cpe, start, w, g,
- ener0, ener1, ener01, +1);
+ ener0, ener1, ener01, 1, +1);
erf = ph_err1.error < ph_err2.error ? &ph_err1 : &ph_err2;
if (erf->pass) {
sce0->ics.prediction_used[sfb] = 1;