Libav 0.7.1
|
00001 /* 00002 * AC-3 encoder float/fixed template 00003 * Copyright (c) 2000 Fabrice Bellard 00004 * Copyright (c) 2006-2011 Justin Ruggles <justin.ruggles@gmail.com> 00005 * Copyright (c) 2006-2010 Prakash Punnoor <prakash@punnoor.de> 00006 * 00007 * This file is part of Libav. 00008 * 00009 * Libav is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * Libav is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with Libav; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 */ 00023 00029 #include <stdint.h> 00030 00031 #include "ac3enc.h" 00032 00033 00034 int AC3_NAME(allocate_sample_buffers)(AC3EncodeContext *s) 00035 { 00036 int ch; 00037 00038 FF_ALLOC_OR_GOTO(s->avctx, s->windowed_samples, AC3_WINDOW_SIZE * 00039 sizeof(*s->windowed_samples), alloc_fail); 00040 FF_ALLOC_OR_GOTO(s->avctx, s->planar_samples, s->channels * sizeof(*s->planar_samples), 00041 alloc_fail); 00042 for (ch = 0; ch < s->channels; ch++) { 00043 FF_ALLOCZ_OR_GOTO(s->avctx, s->planar_samples[ch], 00044 (AC3_FRAME_SIZE+AC3_BLOCK_SIZE) * sizeof(**s->planar_samples), 00045 alloc_fail); 00046 } 00047 00048 return 0; 00049 alloc_fail: 00050 return AVERROR(ENOMEM); 00051 } 00052 00053 00058 void AC3_NAME(deinterleave_input_samples)(AC3EncodeContext *s, 00059 const SampleType *samples) 00060 { 00061 int ch, i; 00062 00063 /* deinterleave and remap input samples */ 00064 for (ch = 0; ch < s->channels; ch++) { 00065 const SampleType *sptr; 00066 int sinc; 00067 00068 /* copy last 256 samples of previous frame to the start of the current frame */ 00069 memcpy(&s->planar_samples[ch][0], &s->planar_samples[ch][AC3_FRAME_SIZE], 00070 AC3_BLOCK_SIZE * sizeof(s->planar_samples[0][0])); 00071 00072 /* deinterleave */ 00073 sinc = s->channels; 00074 sptr = samples + s->channel_map[ch]; 00075 for (i = AC3_BLOCK_SIZE; i < AC3_FRAME_SIZE+AC3_BLOCK_SIZE; i++) { 00076 s->planar_samples[ch][i] = *sptr; 00077 sptr += sinc; 00078 } 00079 } 00080 } 00081 00082 00088 void AC3_NAME(apply_mdct)(AC3EncodeContext *s) 00089 { 00090 int blk, ch; 00091 00092 for (ch = 0; ch < s->channels; ch++) { 00093 for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { 00094 AC3Block *block = &s->blocks[blk]; 00095 const SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE]; 00096 00097 s->apply_window(&s->dsp, s->windowed_samples, input_samples, 00098 s->mdct->window, AC3_WINDOW_SIZE); 00099 00100 if (s->fixed_point) 00101 block->coeff_shift[ch+1] = s->normalize_samples(s); 00102 00103 s->mdct->fft.mdct_calcw(&s->mdct->fft, block->mdct_coef[ch+1], 00104 s->windowed_samples); 00105 } 00106 } 00107 } 00108 00109 00113 static inline float calc_cpl_coord(float energy_ch, float energy_cpl) 00114 { 00115 float coord = 0.125; 00116 if (energy_cpl > 0) 00117 coord *= sqrtf(energy_ch / energy_cpl); 00118 return coord; 00119 } 00120 00121 00130 void AC3_NAME(apply_channel_coupling)(AC3EncodeContext *s) 00131 { 00132 #if CONFIG_AC3ENC_FLOAT 00133 LOCAL_ALIGNED_16(float, cpl_coords, [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]); 00134 LOCAL_ALIGNED_16(int32_t, fixed_cpl_coords, [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]); 00135 int blk, ch, bnd, i, j; 00136 CoefSumType energy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][16] = {{{0}}}; 00137 int cpl_start, num_cpl_coefs; 00138 00139 memset(cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*cpl_coords)); 00140 memset(fixed_cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*fixed_cpl_coords)); 00141 00142 /* align start to 16-byte boundary. align length to multiple of 32. 00143 note: coupling start bin % 4 will always be 1 */ 00144 cpl_start = s->start_freq[CPL_CH] - 1; 00145 num_cpl_coefs = FFALIGN(s->num_cpl_subbands * 12 + 1, 32); 00146 cpl_start = FFMIN(256, cpl_start + num_cpl_coefs) - num_cpl_coefs; 00147 00148 /* calculate coupling channel from fbw channels */ 00149 for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { 00150 AC3Block *block = &s->blocks[blk]; 00151 CoefType *cpl_coef = &block->mdct_coef[CPL_CH][cpl_start]; 00152 if (!block->cpl_in_use) 00153 continue; 00154 memset(cpl_coef, 0, num_cpl_coefs * sizeof(*cpl_coef)); 00155 for (ch = 1; ch <= s->fbw_channels; ch++) { 00156 CoefType *ch_coef = &block->mdct_coef[ch][cpl_start]; 00157 if (!block->channel_in_cpl[ch]) 00158 continue; 00159 for (i = 0; i < num_cpl_coefs; i++) 00160 cpl_coef[i] += ch_coef[i]; 00161 } 00162 00163 /* coefficients must be clipped to +/- 1.0 in order to be encoded */ 00164 s->dsp.vector_clipf(cpl_coef, cpl_coef, -1.0f, 1.0f, num_cpl_coefs); 00165 00166 /* scale coupling coefficients from float to 24-bit fixed-point */ 00167 s->ac3dsp.float_to_fixed24(&block->fixed_coef[CPL_CH][cpl_start], 00168 cpl_coef, num_cpl_coefs); 00169 } 00170 00171 /* calculate energy in each band in coupling channel and each fbw channel */ 00172 /* TODO: possibly use SIMD to speed up energy calculation */ 00173 bnd = 0; 00174 i = s->start_freq[CPL_CH]; 00175 while (i < s->cpl_end_freq) { 00176 int band_size = s->cpl_band_sizes[bnd]; 00177 for (ch = CPL_CH; ch <= s->fbw_channels; ch++) { 00178 for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { 00179 AC3Block *block = &s->blocks[blk]; 00180 if (!block->cpl_in_use || (ch > CPL_CH && !block->channel_in_cpl[ch])) 00181 continue; 00182 for (j = 0; j < band_size; j++) { 00183 CoefType v = block->mdct_coef[ch][i+j]; 00184 MAC_COEF(energy[blk][ch][bnd], v, v); 00185 } 00186 } 00187 } 00188 i += band_size; 00189 bnd++; 00190 } 00191 00192 /* determine which blocks to send new coupling coordinates for */ 00193 for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { 00194 AC3Block *block = &s->blocks[blk]; 00195 AC3Block *block0 = blk ? &s->blocks[blk-1] : NULL; 00196 int new_coords = 0; 00197 CoefSumType coord_diff[AC3_MAX_CHANNELS] = {0,}; 00198 00199 if (block->cpl_in_use) { 00200 /* calculate coupling coordinates for all blocks and calculate the 00201 average difference between coordinates in successive blocks */ 00202 for (ch = 1; ch <= s->fbw_channels; ch++) { 00203 if (!block->channel_in_cpl[ch]) 00204 continue; 00205 00206 for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { 00207 cpl_coords[blk][ch][bnd] = calc_cpl_coord(energy[blk][ch][bnd], 00208 energy[blk][CPL_CH][bnd]); 00209 if (blk > 0 && block0->cpl_in_use && 00210 block0->channel_in_cpl[ch]) { 00211 coord_diff[ch] += fabs(cpl_coords[blk-1][ch][bnd] - 00212 cpl_coords[blk ][ch][bnd]); 00213 } 00214 } 00215 coord_diff[ch] /= s->num_cpl_bands; 00216 } 00217 00218 /* send new coordinates if this is the first block, if previous 00219 * block did not use coupling but this block does, the channels 00220 * using coupling has changed from the previous block, or the 00221 * coordinate difference from the last block for any channel is 00222 * greater than a threshold value. */ 00223 if (blk == 0) { 00224 new_coords = 1; 00225 } else if (!block0->cpl_in_use) { 00226 new_coords = 1; 00227 } else { 00228 for (ch = 1; ch <= s->fbw_channels; ch++) { 00229 if (block->channel_in_cpl[ch] && !block0->channel_in_cpl[ch]) { 00230 new_coords = 1; 00231 break; 00232 } 00233 } 00234 if (!new_coords) { 00235 for (ch = 1; ch <= s->fbw_channels; ch++) { 00236 if (block->channel_in_cpl[ch] && coord_diff[ch] > 0.04) { 00237 new_coords = 1; 00238 break; 00239 } 00240 } 00241 } 00242 } 00243 } 00244 block->new_cpl_coords = new_coords; 00245 } 00246 00247 /* calculate final coupling coordinates, taking into account reusing of 00248 coordinates in successive blocks */ 00249 for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { 00250 blk = 0; 00251 while (blk < AC3_MAX_BLOCKS) { 00252 int blk1; 00253 CoefSumType energy_cpl; 00254 AC3Block *block = &s->blocks[blk]; 00255 00256 if (!block->cpl_in_use) { 00257 blk++; 00258 continue; 00259 } 00260 00261 energy_cpl = energy[blk][CPL_CH][bnd]; 00262 blk1 = blk+1; 00263 while (!s->blocks[blk1].new_cpl_coords && blk1 < AC3_MAX_BLOCKS) { 00264 if (s->blocks[blk1].cpl_in_use) 00265 energy_cpl += energy[blk1][CPL_CH][bnd]; 00266 blk1++; 00267 } 00268 00269 for (ch = 1; ch <= s->fbw_channels; ch++) { 00270 CoefType energy_ch; 00271 if (!block->channel_in_cpl[ch]) 00272 continue; 00273 energy_ch = energy[blk][ch][bnd]; 00274 blk1 = blk+1; 00275 while (!s->blocks[blk1].new_cpl_coords && blk1 < AC3_MAX_BLOCKS) { 00276 if (s->blocks[blk1].cpl_in_use) 00277 energy_ch += energy[blk1][ch][bnd]; 00278 blk1++; 00279 } 00280 cpl_coords[blk][ch][bnd] = calc_cpl_coord(energy_ch, energy_cpl); 00281 } 00282 blk = blk1; 00283 } 00284 } 00285 00286 /* calculate exponents/mantissas for coupling coordinates */ 00287 for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { 00288 AC3Block *block = &s->blocks[blk]; 00289 if (!block->cpl_in_use || !block->new_cpl_coords) 00290 continue; 00291 00292 s->ac3dsp.float_to_fixed24(fixed_cpl_coords[blk][1], 00293 cpl_coords[blk][1], 00294 s->fbw_channels * 16); 00295 s->ac3dsp.extract_exponents(block->cpl_coord_exp[1], 00296 fixed_cpl_coords[blk][1], 00297 s->fbw_channels * 16); 00298 00299 for (ch = 1; ch <= s->fbw_channels; ch++) { 00300 int bnd, min_exp, max_exp, master_exp; 00301 00302 /* determine master exponent */ 00303 min_exp = max_exp = block->cpl_coord_exp[ch][0]; 00304 for (bnd = 1; bnd < s->num_cpl_bands; bnd++) { 00305 int exp = block->cpl_coord_exp[ch][bnd]; 00306 min_exp = FFMIN(exp, min_exp); 00307 max_exp = FFMAX(exp, max_exp); 00308 } 00309 master_exp = ((max_exp - 15) + 2) / 3; 00310 master_exp = FFMAX(master_exp, 0); 00311 while (min_exp < master_exp * 3) 00312 master_exp--; 00313 for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { 00314 block->cpl_coord_exp[ch][bnd] = av_clip(block->cpl_coord_exp[ch][bnd] - 00315 master_exp * 3, 0, 15); 00316 } 00317 block->cpl_master_exp[ch] = master_exp; 00318 00319 /* quantize mantissas */ 00320 for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { 00321 int cpl_exp = block->cpl_coord_exp[ch][bnd]; 00322 int cpl_mant = (fixed_cpl_coords[blk][ch][bnd] << (5 + cpl_exp + master_exp * 3)) >> 24; 00323 if (cpl_exp == 15) 00324 cpl_mant >>= 1; 00325 else 00326 cpl_mant -= 16; 00327 00328 block->cpl_coord_mant[ch][bnd] = cpl_mant; 00329 } 00330 } 00331 } 00332 00333 if (CONFIG_EAC3_ENCODER && s->eac3) 00334 ff_eac3_set_cpl_states(s); 00335 #endif /* CONFIG_AC3ENC_FLOAT */ 00336 } 00337 00338 00342 void AC3_NAME(compute_rematrixing_strategy)(AC3EncodeContext *s) 00343 { 00344 int nb_coefs; 00345 int blk, bnd, i; 00346 AC3Block *block, *av_uninit(block0); 00347 00348 if (s->channel_mode != AC3_CHMODE_STEREO) 00349 return; 00350 00351 for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { 00352 block = &s->blocks[blk]; 00353 block->new_rematrixing_strategy = !blk; 00354 00355 if (!s->rematrixing_enabled) { 00356 block0 = block; 00357 continue; 00358 } 00359 00360 block->num_rematrixing_bands = 4; 00361 if (block->cpl_in_use) { 00362 block->num_rematrixing_bands -= (s->start_freq[CPL_CH] <= 61); 00363 block->num_rematrixing_bands -= (s->start_freq[CPL_CH] == 37); 00364 if (blk && block->num_rematrixing_bands != block0->num_rematrixing_bands) 00365 block->new_rematrixing_strategy = 1; 00366 } 00367 nb_coefs = FFMIN(block->end_freq[1], block->end_freq[2]); 00368 00369 for (bnd = 0; bnd < block->num_rematrixing_bands; bnd++) { 00370 /* calculate calculate sum of squared coeffs for one band in one block */ 00371 int start = ff_ac3_rematrix_band_tab[bnd]; 00372 int end = FFMIN(nb_coefs, ff_ac3_rematrix_band_tab[bnd+1]); 00373 CoefSumType sum[4] = {0,}; 00374 for (i = start; i < end; i++) { 00375 CoefType lt = block->mdct_coef[1][i]; 00376 CoefType rt = block->mdct_coef[2][i]; 00377 CoefType md = lt + rt; 00378 CoefType sd = lt - rt; 00379 MAC_COEF(sum[0], lt, lt); 00380 MAC_COEF(sum[1], rt, rt); 00381 MAC_COEF(sum[2], md, md); 00382 MAC_COEF(sum[3], sd, sd); 00383 } 00384 00385 /* compare sums to determine if rematrixing will be used for this band */ 00386 if (FFMIN(sum[2], sum[3]) < FFMIN(sum[0], sum[1])) 00387 block->rematrixing_flags[bnd] = 1; 00388 else 00389 block->rematrixing_flags[bnd] = 0; 00390 00391 /* determine if new rematrixing flags will be sent */ 00392 if (blk && 00393 block->rematrixing_flags[bnd] != block0->rematrixing_flags[bnd]) { 00394 block->new_rematrixing_strategy = 1; 00395 } 00396 } 00397 block0 = block; 00398 } 00399 }