/src/ffmpeg/libavcodec/aacenc_ltp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * AAC encoder long term prediction extension |
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 long term prediction extension |
25 | | * @author Rostislav Pehlivanov ( atomnuker gmail com ) |
26 | | */ |
27 | | |
28 | | #include "aacenc_ltp.h" |
29 | | #include "aacenc_quantization.h" |
30 | | #include "aacenc_utils.h" |
31 | | |
32 | | /** |
33 | | * Encode LTP data. |
34 | | */ |
35 | | void ff_aac_encode_ltp_info(AACEncContext *s, SingleChannelElement *sce, |
36 | | int common_window) |
37 | 0 | { |
38 | 0 | int i; |
39 | 0 | IndividualChannelStream *ics = &sce->ics; |
40 | 0 | if (s->profile != AV_PROFILE_AAC_LTP || !ics->predictor_present) |
41 | 0 | return; |
42 | 0 | if (common_window) |
43 | 0 | put_bits(&s->pb, 1, 0); |
44 | 0 | put_bits(&s->pb, 1, ics->ltp.present); |
45 | 0 | if (!ics->ltp.present) |
46 | 0 | return; |
47 | 0 | put_bits(&s->pb, 11, ics->ltp.lag); |
48 | 0 | put_bits(&s->pb, 3, ics->ltp.coef_idx); |
49 | 0 | for (i = 0; i < FFMIN(ics->max_sfb, MAX_LTP_LONG_SFB); i++) |
50 | 0 | put_bits(&s->pb, 1, ics->ltp.used[i]); |
51 | 0 | } |
52 | | |
53 | | void ff_aac_ltp_insert_new_frame(AACEncContext *s) |
54 | 0 | { |
55 | 0 | int i, ch, tag, chans, cur_channel, start_ch = 0; |
56 | 0 | ChannelElement *cpe; |
57 | 0 | SingleChannelElement *sce; |
58 | 0 | for (i = 0; i < s->chan_map[0]; i++) { |
59 | 0 | cpe = &s->cpe[i]; |
60 | 0 | tag = s->chan_map[i+1]; |
61 | 0 | chans = tag == TYPE_CPE ? 2 : 1; |
62 | 0 | for (ch = 0; ch < chans; ch++) { |
63 | 0 | sce = &cpe->ch[ch]; |
64 | 0 | cur_channel = start_ch + ch; |
65 | | /* New sample + overlap */ |
66 | 0 | memcpy(&sce->ltp_state[0], &sce->ltp_state[1024], 1024*sizeof(sce->ltp_state[0])); |
67 | 0 | memcpy(&sce->ltp_state[1024], &s->planar_samples[cur_channel][2048], 1024*sizeof(sce->ltp_state[0])); |
68 | 0 | memcpy(&sce->ltp_state[2048], &sce->ret_buf[0], 1024*sizeof(sce->ltp_state[0])); |
69 | 0 | sce->ics.ltp.lag = 0; |
70 | 0 | } |
71 | 0 | start_ch += chans; |
72 | 0 | } |
73 | 0 | } |
74 | | |
75 | | static void get_lag(float *buf, const float *new, LongTermPrediction *ltp) |
76 | 0 | { |
77 | 0 | int i, j, lag = 0, max_corr = 0; |
78 | 0 | float max_ratio = 0.0f; |
79 | 0 | for (i = 0; i < 2048; i++) { |
80 | 0 | float corr, s0 = 0.0f, s1 = 0.0f; |
81 | 0 | const int start = FFMAX(0, i - 1024); |
82 | 0 | for (j = start; j < 2048; j++) { |
83 | 0 | const int idx = j - i + 1024; |
84 | 0 | s0 += new[j]*buf[idx]; |
85 | 0 | s1 += buf[idx]*buf[idx]; |
86 | 0 | } |
87 | 0 | corr = s1 > 0.0f ? s0/sqrt(s1) : 0.0f; |
88 | 0 | if (corr > max_corr) { |
89 | 0 | max_corr = corr; |
90 | 0 | lag = i; |
91 | 0 | max_ratio = corr/(2048-start); |
92 | 0 | } |
93 | 0 | } |
94 | 0 | ltp->lag = FFMAX(av_clip_uintp2(lag, 11), 0); |
95 | 0 | ltp->coef_idx = quant_array_idx(max_ratio, ff_ltp_coef, 8); |
96 | 0 | ltp->coef = ff_ltp_coef[ltp->coef_idx]; |
97 | 0 | } |
98 | | |
99 | | static void generate_samples(float *buf, LongTermPrediction *ltp) |
100 | 0 | { |
101 | 0 | int i, samples_num = 2048; |
102 | 0 | if (!ltp->lag) { |
103 | 0 | ltp->present = 0; |
104 | 0 | return; |
105 | 0 | } else if (ltp->lag < 1024) { |
106 | 0 | samples_num = ltp->lag + 1024; |
107 | 0 | } |
108 | 0 | for (i = 0; i < samples_num; i++) |
109 | 0 | buf[i] = ltp->coef*buf[i + 2048 - ltp->lag]; |
110 | 0 | memset(&buf[i], 0, (2048 - i)*sizeof(float)); |
111 | 0 | } |
112 | | |
113 | | /** |
114 | | * Process LTP parameters |
115 | | * @see Patent WO2006070265A1 |
116 | | */ |
117 | | void ff_aac_update_ltp(AACEncContext *s, SingleChannelElement *sce) |
118 | 0 | { |
119 | 0 | float *pred_signal = &sce->ltp_state[0]; |
120 | 0 | const float *samples = &s->planar_samples[s->cur_channel][1024]; |
121 | |
|
122 | 0 | if (s->profile != AV_PROFILE_AAC_LTP) |
123 | 0 | return; |
124 | | |
125 | | /* Calculate lag */ |
126 | 0 | get_lag(pred_signal, samples, &sce->ics.ltp); |
127 | 0 | generate_samples(pred_signal, &sce->ics.ltp); |
128 | 0 | } |
129 | | |
130 | | void ff_aac_adjust_common_ltp(AACEncContext *s, ChannelElement *cpe) |
131 | 0 | { |
132 | 0 | int sfb, count = 0; |
133 | 0 | SingleChannelElement *sce0 = &cpe->ch[0]; |
134 | 0 | SingleChannelElement *sce1 = &cpe->ch[1]; |
135 | |
|
136 | 0 | if (!cpe->common_window || |
137 | 0 | sce0->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE || |
138 | 0 | sce1->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE) { |
139 | 0 | sce0->ics.ltp.present = 0; |
140 | 0 | return; |
141 | 0 | } |
142 | | |
143 | 0 | for (sfb = 0; sfb < FFMIN(sce0->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++) { |
144 | 0 | int sum = sce0->ics.ltp.used[sfb] + sce1->ics.ltp.used[sfb]; |
145 | 0 | if (sum != 2) { |
146 | 0 | sce0->ics.ltp.used[sfb] = 0; |
147 | 0 | } else { |
148 | 0 | count++; |
149 | 0 | } |
150 | 0 | } |
151 | |
|
152 | 0 | sce0->ics.ltp.present = !!count; |
153 | 0 | sce0->ics.predictor_present = !!count; |
154 | 0 | } |
155 | | |
156 | | /** |
157 | | * Mark LTP sfb's |
158 | | */ |
159 | | void ff_aac_search_for_ltp(AACEncContext *s, SingleChannelElement *sce, |
160 | | int common_window) |
161 | 0 | { |
162 | 0 | int w, g, w2, i, start = 0, count = 0; |
163 | 0 | int saved_bits = -(15 + FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB)); |
164 | 0 | float *C34 = &s->scoefs[128*0], *PCD = &s->scoefs[128*1]; |
165 | 0 | float *PCD34 = &s->scoefs[128*2]; |
166 | 0 | const int max_ltp = FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); |
167 | |
|
168 | 0 | if (sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE) { |
169 | 0 | if (sce->ics.ltp.lag) { |
170 | 0 | memset(&sce->ltp_state[0], 0, 3072*sizeof(sce->ltp_state[0])); |
171 | 0 | memset(&sce->ics.ltp, 0, sizeof(LongTermPrediction)); |
172 | 0 | } |
173 | 0 | return; |
174 | 0 | } |
175 | | |
176 | 0 | if (!sce->ics.ltp.lag || s->lambda > 120.0f) |
177 | 0 | return; |
178 | | |
179 | 0 | for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { |
180 | 0 | start = 0; |
181 | 0 | for (g = 0; g < sce->ics.num_swb; g++) { |
182 | 0 | int bits1 = 0, bits2 = 0; |
183 | 0 | float dist1 = 0.0f, dist2 = 0.0f; |
184 | 0 | if (w*16+g > max_ltp) { |
185 | 0 | start += sce->ics.swb_sizes[g]; |
186 | 0 | continue; |
187 | 0 | } |
188 | 0 | for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { |
189 | 0 | int bits_tmp1, bits_tmp2; |
190 | 0 | FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; |
191 | 0 | for (i = 0; i < sce->ics.swb_sizes[g]; i++) |
192 | 0 | PCD[i] = sce->coeffs[start+(w+w2)*128+i] - sce->lcoeffs[start+(w+w2)*128+i]; |
193 | 0 | s->aacdsp.abs_pow34(C34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]); |
194 | 0 | s->aacdsp.abs_pow34(PCD34, PCD, sce->ics.swb_sizes[g]); |
195 | 0 | dist1 += quantize_band_cost(s, &sce->coeffs[start+(w+w2)*128], C34, sce->ics.swb_sizes[g], |
196 | 0 | sce->sf_idx[(w+w2)*16+g], sce->band_type[(w+w2)*16+g], |
197 | 0 | s->lambda/band->threshold, INFINITY, &bits_tmp1, NULL); |
198 | 0 | dist2 += quantize_band_cost(s, PCD, PCD34, sce->ics.swb_sizes[g], |
199 | 0 | sce->sf_idx[(w+w2)*16+g], |
200 | 0 | sce->band_type[(w+w2)*16+g], |
201 | 0 | s->lambda/band->threshold, INFINITY, &bits_tmp2, NULL); |
202 | 0 | bits1 += bits_tmp1; |
203 | 0 | bits2 += bits_tmp2; |
204 | 0 | } |
205 | 0 | if (dist2 < dist1 && bits2 < bits1) { |
206 | 0 | for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) |
207 | 0 | for (i = 0; i < sce->ics.swb_sizes[g]; i++) |
208 | 0 | sce->coeffs[start+(w+w2)*128+i] -= sce->lcoeffs[start+(w+w2)*128+i]; |
209 | 0 | sce->ics.ltp.used[w*16+g] = 1; |
210 | 0 | saved_bits += bits1 - bits2; |
211 | 0 | count++; |
212 | 0 | } |
213 | 0 | start += sce->ics.swb_sizes[g]; |
214 | 0 | } |
215 | 0 | } |
216 | |
|
217 | 0 | sce->ics.ltp.present = !!count && (saved_bits >= 0); |
218 | 0 | sce->ics.predictor_present = !!sce->ics.ltp.present; |
219 | | |
220 | | /* Reset any marked sfbs */ |
221 | 0 | if (!sce->ics.ltp.present && !!count) { |
222 | 0 | for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { |
223 | 0 | start = 0; |
224 | 0 | for (g = 0; g < sce->ics.num_swb; g++) { |
225 | 0 | if (sce->ics.ltp.used[w*16+g]) { |
226 | 0 | for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { |
227 | 0 | for (i = 0; i < sce->ics.swb_sizes[g]; i++) { |
228 | 0 | sce->coeffs[start+(w+w2)*128+i] += sce->lcoeffs[start+(w+w2)*128+i]; |
229 | 0 | } |
230 | 0 | } |
231 | 0 | } |
232 | 0 | start += sce->ics.swb_sizes[g]; |
233 | 0 | } |
234 | 0 | } |
235 | 0 | } |
236 | 0 | } |