| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * AAC encoder intensity stereo | ||
| 3 | * Copyright (C) 2015 Rostislav Pehlivanov | ||
| 4 | * | ||
| 5 | * This file is part of FFmpeg. | ||
| 6 | * | ||
| 7 | * FFmpeg is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with FFmpeg; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | /** | ||
| 23 | * @file | ||
| 24 | * AAC encoder Intensity Stereo | ||
| 25 | * @author Rostislav Pehlivanov ( atomnuker gmail com ) | ||
| 26 | */ | ||
| 27 | |||
| 28 | #include "aacenc.h" | ||
| 29 | #include "aacenc_utils.h" | ||
| 30 | #include "aacenc_is.h" | ||
| 31 | #include "aacenc_quantization.h" | ||
| 32 | |||
| 33 | /** Frequency in Hz for lower limit of intensity stereo **/ | ||
| 34 | #define INT_STEREO_LOW_LIMIT 6100 | ||
| 35 | |||
| 36 | struct AACISError { | ||
| 37 | int pass; /* 1 if dist2 <= dist1 */ | ||
| 38 | int phase; /* -1 or +1 */ | ||
| 39 | float error; /* fabs(dist1 - dist2) */ | ||
| 40 | float dist1; /* From original coeffs */ | ||
| 41 | float dist2; /* From IS'd coeffs */ | ||
| 42 | float ener01; | ||
| 43 | }; | ||
| 44 | |||
| 45 | 17252 | static struct AACISError aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe, | |
| 46 | int start, int w, int g, float ener0, | ||
| 47 | float ener1, float ener01, int phase) | ||
| 48 | { | ||
| 49 | int i, w2; | ||
| 50 | 17252 | SingleChannelElement *sce0 = &cpe->ch[0]; | |
| 51 | 17252 | SingleChannelElement *sce1 = &cpe->ch[1]; | |
| 52 | 17252 | float *L = sce0->coeffs; | |
| 53 | 17252 | float *R = sce1->coeffs; | |
| 54 | 17252 | float *L34 = &s->scoefs[256*0], *R34 = &s->scoefs[256*1]; | |
| 55 | 17252 | float *IS = &s->scoefs[256*2], *I34 = &s->scoefs[256*3]; | |
| 56 | 17252 | float dist1 = 0.0f, dist2 = 0.0f; | |
| 57 | 17252 | struct AACISError is_error = {0}; | |
| 58 | |||
| 59 |
3/4✓ Branch 0 taken 16813 times.
✓ Branch 1 taken 439 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16813 times.
|
17252 | if (ener01 <= 0 || ener0 <= 0) { |
| 60 | 439 | is_error.pass = 0; | |
| 61 | 439 | return is_error; | |
| 62 | } | ||
| 63 | |||
| 64 |
2/2✓ Branch 0 taken 17009 times.
✓ Branch 1 taken 16813 times.
|
33822 | for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) { |
| 65 | 17009 | FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g]; | |
| 66 | 17009 | FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g]; | |
| 67 | 17009 | int is_band_type, is_sf_idx = FFMAX(1, sce0->sf_idx[w*16+g]-4); | |
| 68 | 17009 | float e01_34 = phase*pos_pow34(ener1/ener0); | |
| 69 | 17009 | float maxval, dist_spec_err = 0.0f; | |
| 70 |
2/2✓ Branch 0 taken 6033 times.
✓ Branch 1 taken 10976 times.
|
17009 | float minthr = FFMIN(band0->threshold, band1->threshold); |
| 71 |
2/2✓ Branch 0 taken 581868 times.
✓ Branch 1 taken 17009 times.
|
598877 | for (i = 0; i < sce0->ics.swb_sizes[g]; i++) |
| 72 | 581868 | IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01); | |
| 73 | 17009 | s->aacdsp.abs_pow34(L34, &L[start+(w+w2)*128], sce0->ics.swb_sizes[g]); | |
| 74 | 17009 | s->aacdsp.abs_pow34(R34, &R[start+(w+w2)*128], sce0->ics.swb_sizes[g]); | |
| 75 | 17009 | s->aacdsp.abs_pow34(I34, IS, sce0->ics.swb_sizes[g]); | |
| 76 | 17009 | maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34); | |
| 77 | 17009 | is_band_type = find_min_book(maxval, is_sf_idx); | |
| 78 | 34018 | dist1 += quantize_band_cost(s, &L[start + (w+w2)*128], L34, | |
| 79 | 17009 | sce0->ics.swb_sizes[g], | |
| 80 | 17009 | sce0->sf_idx[w*16+g], | |
| 81 | 17009 | sce0->band_type[w*16+g], | |
| 82 | 17009 | s->lambda / band0->threshold, INFINITY, NULL, NULL); | |
| 83 | 34018 | dist1 += quantize_band_cost(s, &R[start + (w+w2)*128], R34, | |
| 84 | 17009 | sce1->ics.swb_sizes[g], | |
| 85 | 17009 | sce1->sf_idx[w*16+g], | |
| 86 | 17009 | sce1->band_type[w*16+g], | |
| 87 | 17009 | s->lambda / band1->threshold, INFINITY, NULL, NULL); | |
| 88 | 34018 | dist2 += quantize_band_cost(s, IS, I34, sce0->ics.swb_sizes[g], | |
| 89 | is_sf_idx, is_band_type, | ||
| 90 | 17009 | s->lambda / minthr, INFINITY, NULL, NULL); | |
| 91 |
2/2✓ Branch 0 taken 581868 times.
✓ Branch 1 taken 17009 times.
|
598877 | for (i = 0; i < sce0->ics.swb_sizes[g]; i++) { |
| 92 | 581868 | dist_spec_err += (L34[i] - I34[i])*(L34[i] - I34[i]); | |
| 93 | 581868 | dist_spec_err += (R34[i] - I34[i]*e01_34)*(R34[i] - I34[i]*e01_34); | |
| 94 | } | ||
| 95 | 17009 | dist_spec_err *= s->lambda / minthr; | |
| 96 | 17009 | dist2 += dist_spec_err; | |
| 97 | } | ||
| 98 | |||
| 99 | 16813 | is_error.pass = dist2 <= dist1; | |
| 100 | 16813 | is_error.phase = phase; | |
| 101 | 16813 | is_error.error = dist2 - dist1; | |
| 102 | 16813 | is_error.dist1 = dist1; | |
| 103 | 16813 | is_error.dist2 = dist2; | |
| 104 | 16813 | is_error.ener01 = ener01; | |
| 105 | |||
| 106 | 16813 | return is_error; | |
| 107 | } | ||
| 108 | |||
| 109 | 1333 | void ff_aac_search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe) | |
| 110 | { | ||
| 111 | 1333 | SingleChannelElement *sce0 = &cpe->ch[0]; | |
| 112 | 1333 | SingleChannelElement *sce1 = &cpe->ch[1]; | |
| 113 | 1333 | int start = 0, count = 0, w, w2, g, i, prev_sf1 = -1, prev_bt = -1, prev_is = 0; | |
| 114 | 1333 | const float freq_mult = avctx->sample_rate/(1024.0f/sce0->ics.num_windows)/2.0f; | |
| 115 | uint8_t nextband1[128]; | ||
| 116 | |||
| 117 |
2/2✓ Branch 0 taken 707 times.
✓ Branch 1 taken 626 times.
|
1333 | if (!cpe->common_window) |
| 118 | 707 | return; | |
| 119 | |||
| 120 | /** Scout out next nonzero bands */ | ||
| 121 | 626 | ff_init_nextband_map(sce1, nextband1); | |
| 122 | |||
| 123 |
2/2✓ Branch 0 taken 660 times.
✓ Branch 1 taken 626 times.
|
1286 | for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) { |
| 124 | 660 | start = 0; | |
| 125 |
2/2✓ Branch 0 taken 30660 times.
✓ Branch 1 taken 660 times.
|
31320 | for (g = 0; g < sce0->ics.num_swb; g++) { |
| 126 |
2/2✓ Branch 0 taken 9535 times.
✓ Branch 1 taken 21125 times.
|
30660 | if (start*freq_mult > INT_STEREO_LOW_LIMIT*(s->lambda/170.0f) && |
| 127 |
4/4✓ Branch 0 taken 9286 times.
✓ Branch 1 taken 249 times.
✓ Branch 2 taken 8682 times.
✓ Branch 3 taken 604 times.
|
9535 | cpe->ch[0].band_type[w*16+g] != NOISE_BT && !cpe->ch[0].zeroes[w*16+g] && |
| 128 |
4/6✓ Branch 0 taken 8626 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 8626 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8626 times.
✗ Branch 5 not taken.
|
17308 | cpe->ch[1].band_type[w*16+g] != NOISE_BT && !cpe->ch[1].zeroes[w*16+g] && |
| 129 | 8626 | ff_sfdelta_can_remove_band(sce1, nextband1, prev_sf1, w*16+g)) { | |
| 130 | 8626 | float ener0 = 0.0f, ener1 = 0.0f, ener01 = 0.0f, ener01p = 0.0f; | |
| 131 | struct AACISError ph_err1, ph_err2, *best; | ||
| 132 |
2/2✓ Branch 0 taken 8738 times.
✓ Branch 1 taken 8626 times.
|
17364 | for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) { |
| 133 |
2/2✓ Branch 0 taken 297956 times.
✓ Branch 1 taken 8738 times.
|
306694 | for (i = 0; i < sce0->ics.swb_sizes[g]; i++) { |
| 134 | 297956 | float coef0 = sce0->coeffs[start+(w+w2)*128+i]; | |
| 135 | 297956 | float coef1 = sce1->coeffs[start+(w+w2)*128+i]; | |
| 136 | 297956 | ener0 += coef0*coef0; | |
| 137 | 297956 | ener1 += coef1*coef1; | |
| 138 | 297956 | ener01 += (coef0 + coef1)*(coef0 + coef1); | |
| 139 | 297956 | ener01p += (coef0 - coef1)*(coef0 - coef1); | |
| 140 | } | ||
| 141 | } | ||
| 142 | 8626 | ph_err1 = aac_is_encoding_err(s, cpe, start, w, g, | |
| 143 | ener0, ener1, ener01p, -1); | ||
| 144 | 8626 | ph_err2 = aac_is_encoding_err(s, cpe, start, w, g, | |
| 145 | ener0, ener1, ener01, +1); | ||
| 146 |
4/4✓ Branch 0 taken 7886 times.
✓ Branch 1 taken 740 times.
✓ Branch 2 taken 1019 times.
✓ Branch 3 taken 6867 times.
|
8626 | best = (ph_err1.pass && ph_err1.error < ph_err2.error) ? &ph_err1 : &ph_err2; |
| 147 |
2/2✓ Branch 0 taken 8545 times.
✓ Branch 1 taken 81 times.
|
8626 | if (best->pass) { |
| 148 | 8545 | cpe->is_mask[w*16+g] = 1; | |
| 149 | 8545 | cpe->ms_mask[w*16+g] = 0; | |
| 150 | 8545 | cpe->ch[0].is_ener[w*16+g] = sqrt(ener0 / best->ener01); | |
| 151 | 8545 | cpe->ch[1].is_ener[w*16+g] = ener0/ener1; | |
| 152 |
2/2✓ Branch 0 taken 7526 times.
✓ Branch 1 taken 1019 times.
|
8545 | cpe->ch[1].band_type[w*16+g] = (best->phase > 0) ? INTENSITY_BT : INTENSITY_BT2; |
| 153 |
4/4✓ Branch 0 taken 8031 times.
✓ Branch 1 taken 514 times.
✓ Branch 2 taken 2367 times.
✓ Branch 3 taken 5664 times.
|
8545 | if (prev_is && prev_bt != cpe->ch[1].band_type[w*16+g]) { |
| 154 | /** Flip M/S mask and pick the other CB, since it encodes more efficiently */ | ||
| 155 | 2367 | cpe->ms_mask[w*16+g] = 1; | |
| 156 |
2/2✓ Branch 0 taken 1793 times.
✓ Branch 1 taken 574 times.
|
2367 | cpe->ch[1].band_type[w*16+g] = (best->phase > 0) ? INTENSITY_BT2 : INTENSITY_BT; |
| 157 | } | ||
| 158 | 8545 | prev_bt = cpe->ch[1].band_type[w*16+g]; | |
| 159 | 8545 | count++; | |
| 160 | } | ||
| 161 | } | ||
| 162 |
4/4✓ Branch 0 taken 27477 times.
✓ Branch 1 taken 3183 times.
✓ Branch 2 taken 17699 times.
✓ Branch 3 taken 9778 times.
|
30660 | if (!sce1->zeroes[w*16+g] && sce1->band_type[w*16+g] < RESERVED_BT) |
| 163 | 17699 | prev_sf1 = sce1->sf_idx[w*16+g]; | |
| 164 | 30660 | prev_is = cpe->is_mask[w*16+g]; | |
| 165 | 30660 | start += sce0->ics.swb_sizes[g]; | |
| 166 | } | ||
| 167 | } | ||
| 168 | 626 | cpe->is_mode = !!count; | |
| 169 | } | ||
| 170 |