...
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
clean::
|
||||
$(RM) $(CLEANSUFFIXES:%=libavcodec/opus/%)
|
||||
|
||||
OBJS-$(CONFIG_OPUS_DECODER) += \
|
||||
opus/dec.o \
|
||||
opus/dec_celt.o \
|
||||
opus/celt.o \
|
||||
opus/pvq.o \
|
||||
opus/silk.o \
|
||||
opus/tab.o \
|
||||
opus/dsp.o \
|
||||
opus/parse.o \
|
||||
opus/rc.o \
|
||||
|
||||
|
||||
OBJS-$(CONFIG_OPUS_PARSER) += \
|
||||
opus/parser.o \
|
||||
opus/parse.o \
|
||||
|
||||
|
||||
OBJS-$(CONFIG_OPUS_ENCODER) += \
|
||||
opus/enc.o \
|
||||
opus/enc_psy.o \
|
||||
opus/celt.o \
|
||||
opus/pvq.o \
|
||||
opus/rc.o \
|
||||
opus/tab.o \
|
||||
|
||||
|
||||
libavcodec/opus/%.o: CPPFLAGS += -I$(SRC_PATH)/libavcodec/
|
||||
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "celt.h"
|
||||
#include "pvq.h"
|
||||
#include "tab.h"
|
||||
|
||||
void ff_celt_quant_bands(CeltFrame *f, OpusRangeCoder *rc)
|
||||
{
|
||||
float lowband_scratch[8 * 22];
|
||||
float norm1[2 * 8 * 100];
|
||||
float *norm2 = norm1 + 8 * 100;
|
||||
|
||||
int totalbits = (f->framebits << 3) - f->anticollapse_needed;
|
||||
|
||||
int update_lowband = 1;
|
||||
int lowband_offset = 0;
|
||||
|
||||
int i, j;
|
||||
|
||||
for (i = f->start_band; i < f->end_band; i++) {
|
||||
uint32_t cm[2] = { (1 << f->blocks) - 1, (1 << f->blocks) - 1 };
|
||||
int band_offset = ff_celt_freq_bands[i] << f->size;
|
||||
int band_size = ff_celt_freq_range[i] << f->size;
|
||||
float *X = f->block[0].coeffs + band_offset;
|
||||
float *Y = (f->channels == 2) ? f->block[1].coeffs + band_offset : NULL;
|
||||
float *norm_loc1, *norm_loc2;
|
||||
|
||||
int consumed = opus_rc_tell_frac(rc);
|
||||
int effective_lowband = -1;
|
||||
int b = 0;
|
||||
|
||||
/* Compute how many bits we want to allocate to this band */
|
||||
if (i != f->start_band)
|
||||
f->remaining -= consumed;
|
||||
f->remaining2 = totalbits - consumed - 1;
|
||||
if (i <= f->coded_bands - 1) {
|
||||
int curr_balance = f->remaining / FFMIN(3, f->coded_bands-i);
|
||||
b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[i] + curr_balance), 14);
|
||||
}
|
||||
|
||||
if ((ff_celt_freq_bands[i] - ff_celt_freq_range[i] >= ff_celt_freq_bands[f->start_band] ||
|
||||
i == f->start_band + 1) && (update_lowband || lowband_offset == 0))
|
||||
lowband_offset = i;
|
||||
|
||||
if (i == f->start_band + 1) {
|
||||
/* Special Hybrid Folding (RFC 8251 section 9). Copy the first band into
|
||||
the second to ensure the second band never has to use the LCG. */
|
||||
int count = (ff_celt_freq_range[i] - ff_celt_freq_range[i-1]) << f->size;
|
||||
|
||||
memcpy(&norm1[band_offset], &norm1[band_offset - count], count * sizeof(float));
|
||||
|
||||
if (f->channels == 2)
|
||||
memcpy(&norm2[band_offset], &norm2[band_offset - count], count * sizeof(float));
|
||||
}
|
||||
|
||||
/* Get a conservative estimate of the collapse_mask's for the bands we're
|
||||
going to be folding from. */
|
||||
if (lowband_offset != 0 && (f->spread != CELT_SPREAD_AGGRESSIVE ||
|
||||
f->blocks > 1 || f->tf_change[i] < 0)) {
|
||||
int foldstart, foldend;
|
||||
|
||||
/* This ensures we never repeat spectral content within one band */
|
||||
effective_lowband = FFMAX(ff_celt_freq_bands[f->start_band],
|
||||
ff_celt_freq_bands[lowband_offset] - ff_celt_freq_range[i]);
|
||||
foldstart = lowband_offset;
|
||||
while (ff_celt_freq_bands[--foldstart] > effective_lowband);
|
||||
foldend = lowband_offset - 1;
|
||||
while (++foldend < i && ff_celt_freq_bands[foldend] < effective_lowband + ff_celt_freq_range[i]);
|
||||
|
||||
cm[0] = cm[1] = 0;
|
||||
for (j = foldstart; j < foldend; j++) {
|
||||
cm[0] |= f->block[0].collapse_masks[j];
|
||||
cm[1] |= f->block[f->channels - 1].collapse_masks[j];
|
||||
}
|
||||
}
|
||||
|
||||
if (f->dual_stereo && i == f->intensity_stereo) {
|
||||
/* Switch off dual stereo to do intensity */
|
||||
f->dual_stereo = 0;
|
||||
for (j = ff_celt_freq_bands[f->start_band] << f->size; j < band_offset; j++)
|
||||
norm1[j] = (norm1[j] + norm2[j]) / 2;
|
||||
}
|
||||
|
||||
norm_loc1 = effective_lowband != -1 ? norm1 + (effective_lowband << f->size) : NULL;
|
||||
norm_loc2 = effective_lowband != -1 ? norm2 + (effective_lowband << f->size) : NULL;
|
||||
|
||||
if (f->dual_stereo) {
|
||||
cm[0] = f->pvq->quant_band(f->pvq, f, rc, i, X, NULL, band_size, b >> 1,
|
||||
f->blocks, norm_loc1, f->size,
|
||||
norm1 + band_offset, 0, 1.0f,
|
||||
lowband_scratch, cm[0]);
|
||||
|
||||
cm[1] = f->pvq->quant_band(f->pvq, f, rc, i, Y, NULL, band_size, b >> 1,
|
||||
f->blocks, norm_loc2, f->size,
|
||||
norm2 + band_offset, 0, 1.0f,
|
||||
lowband_scratch, cm[1]);
|
||||
} else {
|
||||
cm[0] = f->pvq->quant_band(f->pvq, f, rc, i, X, Y, band_size, b >> 0,
|
||||
f->blocks, norm_loc1, f->size,
|
||||
norm1 + band_offset, 0, 1.0f,
|
||||
lowband_scratch, cm[0] | cm[1]);
|
||||
cm[1] = cm[0];
|
||||
}
|
||||
|
||||
f->block[0].collapse_masks[i] = (uint8_t)cm[0];
|
||||
f->block[f->channels - 1].collapse_masks[i] = (uint8_t)cm[1];
|
||||
f->remaining += f->pulses[i] + consumed;
|
||||
|
||||
/* Update the folding position only as long as we have 1 bit/sample depth */
|
||||
update_lowband = (b > band_size << 3);
|
||||
}
|
||||
}
|
||||
|
||||
#define NORMC(bits) ((bits) << (f->channels - 1) << f->size >> 2)
|
||||
|
||||
void ff_celt_bitalloc(CeltFrame *f, OpusRangeCoder *rc, int encode)
|
||||
{
|
||||
int i, j, low, high, total, done, bandbits, remaining, tbits_8ths;
|
||||
int skip_startband = f->start_band;
|
||||
int skip_bit = 0;
|
||||
int intensitystereo_bit = 0;
|
||||
int dualstereo_bit = 0;
|
||||
int dynalloc = 6;
|
||||
int extrabits = 0;
|
||||
|
||||
int boost[CELT_MAX_BANDS] = { 0 };
|
||||
int trim_offset[CELT_MAX_BANDS];
|
||||
int threshold[CELT_MAX_BANDS];
|
||||
int bits1[CELT_MAX_BANDS];
|
||||
int bits2[CELT_MAX_BANDS];
|
||||
|
||||
/* Spread */
|
||||
if (opus_rc_tell(rc) + 4 <= f->framebits) {
|
||||
if (encode)
|
||||
ff_opus_rc_enc_cdf(rc, f->spread, ff_celt_model_spread);
|
||||
else
|
||||
f->spread = ff_opus_rc_dec_cdf(rc, ff_celt_model_spread);
|
||||
} else {
|
||||
f->spread = CELT_SPREAD_NORMAL;
|
||||
}
|
||||
|
||||
/* Initialize static allocation caps */
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++)
|
||||
f->caps[i] = NORMC((ff_celt_static_caps[f->size][f->channels - 1][i] + 64) * ff_celt_freq_range[i]);
|
||||
|
||||
/* Band boosts */
|
||||
tbits_8ths = f->framebits << 3;
|
||||
for (i = f->start_band; i < f->end_band; i++) {
|
||||
int quanta = ff_celt_freq_range[i] << (f->channels - 1) << f->size;
|
||||
int b_dynalloc = dynalloc;
|
||||
int boost_amount = f->alloc_boost[i];
|
||||
quanta = FFMIN(quanta << 3, FFMAX(6 << 3, quanta));
|
||||
|
||||
while (opus_rc_tell_frac(rc) + (b_dynalloc << 3) < tbits_8ths && boost[i] < f->caps[i]) {
|
||||
int is_boost;
|
||||
if (encode) {
|
||||
is_boost = boost_amount--;
|
||||
ff_opus_rc_enc_log(rc, is_boost, b_dynalloc);
|
||||
} else {
|
||||
is_boost = ff_opus_rc_dec_log(rc, b_dynalloc);
|
||||
}
|
||||
|
||||
if (!is_boost)
|
||||
break;
|
||||
|
||||
boost[i] += quanta;
|
||||
tbits_8ths -= quanta;
|
||||
|
||||
b_dynalloc = 1;
|
||||
}
|
||||
|
||||
if (boost[i])
|
||||
dynalloc = FFMAX(dynalloc - 1, 2);
|
||||
}
|
||||
|
||||
/* Allocation trim */
|
||||
if (!encode)
|
||||
f->alloc_trim = 5;
|
||||
if (opus_rc_tell_frac(rc) + (6 << 3) <= tbits_8ths)
|
||||
if (encode)
|
||||
ff_opus_rc_enc_cdf(rc, f->alloc_trim, ff_celt_model_alloc_trim);
|
||||
else
|
||||
f->alloc_trim = ff_opus_rc_dec_cdf(rc, ff_celt_model_alloc_trim);
|
||||
|
||||
/* Anti-collapse bit reservation */
|
||||
tbits_8ths = (f->framebits << 3) - opus_rc_tell_frac(rc) - 1;
|
||||
f->anticollapse_needed = 0;
|
||||
if (f->transient && f->size >= 2 && tbits_8ths >= ((f->size + 2) << 3))
|
||||
f->anticollapse_needed = 1 << 3;
|
||||
tbits_8ths -= f->anticollapse_needed;
|
||||
|
||||
/* Band skip bit reservation */
|
||||
if (tbits_8ths >= 1 << 3)
|
||||
skip_bit = 1 << 3;
|
||||
tbits_8ths -= skip_bit;
|
||||
|
||||
/* Intensity/dual stereo bit reservation */
|
||||
if (f->channels == 2) {
|
||||
intensitystereo_bit = ff_celt_log2_frac[f->end_band - f->start_band];
|
||||
if (intensitystereo_bit <= tbits_8ths) {
|
||||
tbits_8ths -= intensitystereo_bit;
|
||||
if (tbits_8ths >= 1 << 3) {
|
||||
dualstereo_bit = 1 << 3;
|
||||
tbits_8ths -= 1 << 3;
|
||||
}
|
||||
} else {
|
||||
intensitystereo_bit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Trim offsets */
|
||||
for (i = f->start_band; i < f->end_band; i++) {
|
||||
int trim = f->alloc_trim - 5 - f->size;
|
||||
int band = ff_celt_freq_range[i] * (f->end_band - i - 1);
|
||||
int duration = f->size + 3;
|
||||
int scale = duration + f->channels - 1;
|
||||
|
||||
/* PVQ minimum allocation threshold, below this value the band is
|
||||
* skipped */
|
||||
threshold[i] = FFMAX(3 * ff_celt_freq_range[i] << duration >> 4,
|
||||
f->channels << 3);
|
||||
|
||||
trim_offset[i] = trim * (band << scale) >> 6;
|
||||
|
||||
if (ff_celt_freq_range[i] << f->size == 1)
|
||||
trim_offset[i] -= f->channels << 3;
|
||||
}
|
||||
|
||||
/* Bisection */
|
||||
low = 1;
|
||||
high = CELT_VECTORS - 1;
|
||||
while (low <= high) {
|
||||
int center = (low + high) >> 1;
|
||||
done = total = 0;
|
||||
|
||||
for (i = f->end_band - 1; i >= f->start_band; i--) {
|
||||
bandbits = NORMC(ff_celt_freq_range[i] * ff_celt_static_alloc[center][i]);
|
||||
|
||||
if (bandbits)
|
||||
bandbits = FFMAX(bandbits + trim_offset[i], 0);
|
||||
bandbits += boost[i];
|
||||
|
||||
if (bandbits >= threshold[i] || done) {
|
||||
done = 1;
|
||||
total += FFMIN(bandbits, f->caps[i]);
|
||||
} else if (bandbits >= f->channels << 3) {
|
||||
total += f->channels << 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (total > tbits_8ths)
|
||||
high = center - 1;
|
||||
else
|
||||
low = center + 1;
|
||||
}
|
||||
high = low--;
|
||||
|
||||
/* Bisection */
|
||||
for (i = f->start_band; i < f->end_band; i++) {
|
||||
bits1[i] = NORMC(ff_celt_freq_range[i] * ff_celt_static_alloc[low][i]);
|
||||
bits2[i] = high >= CELT_VECTORS ? f->caps[i] :
|
||||
NORMC(ff_celt_freq_range[i] * ff_celt_static_alloc[high][i]);
|
||||
|
||||
if (bits1[i])
|
||||
bits1[i] = FFMAX(bits1[i] + trim_offset[i], 0);
|
||||
if (bits2[i])
|
||||
bits2[i] = FFMAX(bits2[i] + trim_offset[i], 0);
|
||||
|
||||
if (low)
|
||||
bits1[i] += boost[i];
|
||||
bits2[i] += boost[i];
|
||||
|
||||
if (boost[i])
|
||||
skip_startband = i;
|
||||
bits2[i] = FFMAX(bits2[i] - bits1[i], 0);
|
||||
}
|
||||
|
||||
/* Bisection */
|
||||
low = 0;
|
||||
high = 1 << CELT_ALLOC_STEPS;
|
||||
for (i = 0; i < CELT_ALLOC_STEPS; i++) {
|
||||
int center = (low + high) >> 1;
|
||||
done = total = 0;
|
||||
|
||||
for (j = f->end_band - 1; j >= f->start_band; j--) {
|
||||
bandbits = bits1[j] + (center * bits2[j] >> CELT_ALLOC_STEPS);
|
||||
|
||||
if (bandbits >= threshold[j] || done) {
|
||||
done = 1;
|
||||
total += FFMIN(bandbits, f->caps[j]);
|
||||
} else if (bandbits >= f->channels << 3)
|
||||
total += f->channels << 3;
|
||||
}
|
||||
if (total > tbits_8ths)
|
||||
high = center;
|
||||
else
|
||||
low = center;
|
||||
}
|
||||
|
||||
/* Bisection */
|
||||
done = total = 0;
|
||||
for (i = f->end_band - 1; i >= f->start_band; i--) {
|
||||
bandbits = bits1[i] + (low * bits2[i] >> CELT_ALLOC_STEPS);
|
||||
|
||||
if (bandbits >= threshold[i] || done)
|
||||
done = 1;
|
||||
else
|
||||
bandbits = (bandbits >= f->channels << 3) ?
|
||||
f->channels << 3 : 0;
|
||||
|
||||
bandbits = FFMIN(bandbits, f->caps[i]);
|
||||
f->pulses[i] = bandbits;
|
||||
total += bandbits;
|
||||
}
|
||||
|
||||
/* Band skipping */
|
||||
for (f->coded_bands = f->end_band; ; f->coded_bands--) {
|
||||
int allocation;
|
||||
j = f->coded_bands - 1;
|
||||
|
||||
if (j == skip_startband) {
|
||||
/* all remaining bands are not skipped */
|
||||
tbits_8ths += skip_bit;
|
||||
break;
|
||||
}
|
||||
|
||||
/* determine the number of bits available for coding "do not skip" markers */
|
||||
remaining = tbits_8ths - total;
|
||||
bandbits = remaining / (ff_celt_freq_bands[j+1] - ff_celt_freq_bands[f->start_band]);
|
||||
remaining -= bandbits * (ff_celt_freq_bands[j+1] - ff_celt_freq_bands[f->start_band]);
|
||||
allocation = f->pulses[j] + bandbits * ff_celt_freq_range[j];
|
||||
allocation += FFMAX(remaining - (ff_celt_freq_bands[j] - ff_celt_freq_bands[f->start_band]), 0);
|
||||
|
||||
/* a "do not skip" marker is only coded if the allocation is
|
||||
* above the chosen threshold */
|
||||
if (allocation >= FFMAX(threshold[j], (f->channels + 1) << 3)) {
|
||||
int do_not_skip;
|
||||
if (encode) {
|
||||
do_not_skip = f->coded_bands <= f->skip_band_floor;
|
||||
ff_opus_rc_enc_log(rc, do_not_skip, 1);
|
||||
} else {
|
||||
do_not_skip = ff_opus_rc_dec_log(rc, 1);
|
||||
}
|
||||
|
||||
if (do_not_skip)
|
||||
break;
|
||||
|
||||
total += 1 << 3;
|
||||
allocation -= 1 << 3;
|
||||
}
|
||||
|
||||
/* the band is skipped, so reclaim its bits */
|
||||
total -= f->pulses[j];
|
||||
if (intensitystereo_bit) {
|
||||
total -= intensitystereo_bit;
|
||||
intensitystereo_bit = ff_celt_log2_frac[j - f->start_band];
|
||||
total += intensitystereo_bit;
|
||||
}
|
||||
|
||||
total += f->pulses[j] = (allocation >= f->channels << 3) ? f->channels << 3 : 0;
|
||||
}
|
||||
|
||||
/* IS start band */
|
||||
if (encode) {
|
||||
if (intensitystereo_bit) {
|
||||
f->intensity_stereo = FFMIN(f->intensity_stereo, f->coded_bands);
|
||||
ff_opus_rc_enc_uint(rc, f->intensity_stereo, f->coded_bands + 1 - f->start_band);
|
||||
}
|
||||
} else {
|
||||
f->intensity_stereo = f->dual_stereo = 0;
|
||||
if (intensitystereo_bit)
|
||||
f->intensity_stereo = f->start_band + ff_opus_rc_dec_uint(rc, f->coded_bands + 1 - f->start_band);
|
||||
}
|
||||
|
||||
/* DS flag */
|
||||
if (f->intensity_stereo <= f->start_band)
|
||||
tbits_8ths += dualstereo_bit; /* no intensity stereo means no dual stereo */
|
||||
else if (dualstereo_bit)
|
||||
if (encode)
|
||||
ff_opus_rc_enc_log(rc, f->dual_stereo, 1);
|
||||
else
|
||||
f->dual_stereo = ff_opus_rc_dec_log(rc, 1);
|
||||
|
||||
/* Supply the remaining bits in this frame to lower bands */
|
||||
remaining = tbits_8ths - total;
|
||||
bandbits = remaining / (ff_celt_freq_bands[f->coded_bands] - ff_celt_freq_bands[f->start_band]);
|
||||
remaining -= bandbits * (ff_celt_freq_bands[f->coded_bands] - ff_celt_freq_bands[f->start_band]);
|
||||
for (i = f->start_band; i < f->coded_bands; i++) {
|
||||
const int bits = FFMIN(remaining, ff_celt_freq_range[i]);
|
||||
f->pulses[i] += bits + bandbits * ff_celt_freq_range[i];
|
||||
remaining -= bits;
|
||||
}
|
||||
|
||||
/* Finally determine the allocation */
|
||||
for (i = f->start_band; i < f->coded_bands; i++) {
|
||||
int N = ff_celt_freq_range[i] << f->size;
|
||||
int prev_extra = extrabits;
|
||||
f->pulses[i] += extrabits;
|
||||
|
||||
if (N > 1) {
|
||||
int dof; /* degrees of freedom */
|
||||
int temp; /* dof * channels * log(dof) */
|
||||
int fine_bits;
|
||||
int max_bits;
|
||||
int offset; /* fine energy quantization offset, i.e.
|
||||
* extra bits assigned over the standard
|
||||
* totalbits/dof */
|
||||
|
||||
extrabits = FFMAX(f->pulses[i] - f->caps[i], 0);
|
||||
f->pulses[i] -= extrabits;
|
||||
|
||||
/* intensity stereo makes use of an extra degree of freedom */
|
||||
dof = N * f->channels + (f->channels == 2 && N > 2 && !f->dual_stereo && i < f->intensity_stereo);
|
||||
temp = dof * (ff_celt_log_freq_range[i] + (f->size << 3));
|
||||
offset = (temp >> 1) - dof * CELT_FINE_OFFSET;
|
||||
if (N == 2) /* dof=2 is the only case that doesn't fit the model */
|
||||
offset += dof << 1;
|
||||
|
||||
/* grant an additional bias for the first and second pulses */
|
||||
if (f->pulses[i] + offset < 2 * (dof << 3))
|
||||
offset += temp >> 2;
|
||||
else if (f->pulses[i] + offset < 3 * (dof << 3))
|
||||
offset += temp >> 3;
|
||||
|
||||
fine_bits = (f->pulses[i] + offset + (dof << 2)) / (dof << 3);
|
||||
max_bits = FFMIN((f->pulses[i] >> 3) >> (f->channels - 1), CELT_MAX_FINE_BITS);
|
||||
max_bits = FFMAX(max_bits, 0);
|
||||
f->fine_bits[i] = av_clip(fine_bits, 0, max_bits);
|
||||
|
||||
/* If fine_bits was rounded down or capped,
|
||||
* give priority for the final fine energy pass */
|
||||
f->fine_priority[i] = (f->fine_bits[i] * (dof << 3) >= f->pulses[i] + offset);
|
||||
|
||||
/* the remaining bits are assigned to PVQ */
|
||||
f->pulses[i] -= f->fine_bits[i] << (f->channels - 1) << 3;
|
||||
} else {
|
||||
/* all bits go to fine energy except for the sign bit */
|
||||
extrabits = FFMAX(f->pulses[i] - (f->channels << 3), 0);
|
||||
f->pulses[i] -= extrabits;
|
||||
f->fine_bits[i] = 0;
|
||||
f->fine_priority[i] = 1;
|
||||
}
|
||||
|
||||
/* hand back a limited number of extra fine energy bits to this band */
|
||||
if (extrabits > 0) {
|
||||
int fineextra = FFMIN(extrabits >> (f->channels + 2),
|
||||
CELT_MAX_FINE_BITS - f->fine_bits[i]);
|
||||
f->fine_bits[i] += fineextra;
|
||||
|
||||
fineextra <<= f->channels + 2;
|
||||
f->fine_priority[i] = (fineextra >= extrabits - prev_extra);
|
||||
extrabits -= fineextra;
|
||||
}
|
||||
}
|
||||
f->remaining = extrabits;
|
||||
|
||||
/* skipped bands dedicate all of their bits for fine energy */
|
||||
for (; i < f->end_band; i++) {
|
||||
f->fine_bits[i] = f->pulses[i] >> (f->channels - 1) >> 3;
|
||||
f->pulses[i] = 0;
|
||||
f->fine_priority[i] = f->fine_bits[i] < 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Opus decoder/encoder CELT functions
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
* Copyright (c) 2016 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_CELT_H
|
||||
#define AVCODEC_OPUS_CELT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
|
||||
#include "dsp.h"
|
||||
#include "rc.h"
|
||||
|
||||
#include "libavutil/float_dsp.h"
|
||||
#include "libavutil/libm.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
#include "libavutil/tx.h"
|
||||
|
||||
#define CELT_SHORT_BLOCKSIZE 120
|
||||
#define CELT_OVERLAP CELT_SHORT_BLOCKSIZE
|
||||
#define CELT_MAX_LOG_BLOCKS 3
|
||||
#define CELT_MAX_FRAME_SIZE (CELT_SHORT_BLOCKSIZE * (1 << CELT_MAX_LOG_BLOCKS))
|
||||
#define CELT_MAX_BANDS 21
|
||||
|
||||
#define CELT_VECTORS 11
|
||||
#define CELT_ALLOC_STEPS 6
|
||||
#define CELT_FINE_OFFSET 21
|
||||
#define CELT_MAX_FINE_BITS 8
|
||||
#define CELT_NORM_SCALE 16384
|
||||
#define CELT_QTHETA_OFFSET 4
|
||||
#define CELT_QTHETA_OFFSET_TWOPHASE 16
|
||||
#define CELT_POSTFILTER_MINPERIOD 15
|
||||
#define CELT_ENERGY_SILENCE (-28.0f)
|
||||
|
||||
enum CeltSpread {
|
||||
CELT_SPREAD_NONE,
|
||||
CELT_SPREAD_LIGHT,
|
||||
CELT_SPREAD_NORMAL,
|
||||
CELT_SPREAD_AGGRESSIVE
|
||||
};
|
||||
|
||||
enum CeltBlockSize {
|
||||
CELT_BLOCK_120,
|
||||
CELT_BLOCK_240,
|
||||
CELT_BLOCK_480,
|
||||
CELT_BLOCK_960,
|
||||
|
||||
CELT_BLOCK_NB
|
||||
};
|
||||
|
||||
typedef struct CeltBlock {
|
||||
float energy[CELT_MAX_BANDS];
|
||||
float lin_energy[CELT_MAX_BANDS];
|
||||
float error_energy[CELT_MAX_BANDS];
|
||||
float prev_energy[2][CELT_MAX_BANDS];
|
||||
|
||||
uint8_t collapse_masks[CELT_MAX_BANDS];
|
||||
|
||||
/* buffer for mdct output + postfilter */
|
||||
DECLARE_ALIGNED(32, float, buf)[2048];
|
||||
DECLARE_ALIGNED(32, float, coeffs)[CELT_MAX_FRAME_SIZE];
|
||||
|
||||
/* Used by the encoder */
|
||||
DECLARE_ALIGNED(32, float, overlap)[FFALIGN(CELT_OVERLAP, 16)];
|
||||
DECLARE_ALIGNED(32, float, samples)[FFALIGN(CELT_MAX_FRAME_SIZE, 16)];
|
||||
|
||||
/* postfilter parameters */
|
||||
int pf_period_new;
|
||||
float pf_gains_new[3];
|
||||
int pf_period;
|
||||
float pf_gains[3];
|
||||
int pf_period_old;
|
||||
float pf_gains_old[3];
|
||||
|
||||
float emph_coeff;
|
||||
} CeltBlock;
|
||||
|
||||
typedef struct CeltFrame {
|
||||
// constant values that do not change during context lifetime
|
||||
AVCodecContext *avctx;
|
||||
AVTXContext *tx[4];
|
||||
av_tx_fn tx_fn[4];
|
||||
AVFloatDSPContext *dsp;
|
||||
CeltBlock block[2];
|
||||
struct CeltPVQ *pvq;
|
||||
OpusDSP opusdsp;
|
||||
int channels;
|
||||
int output_channels;
|
||||
int apply_phase_inv;
|
||||
|
||||
enum CeltBlockSize size;
|
||||
int start_band;
|
||||
int end_band;
|
||||
int coded_bands;
|
||||
int transient;
|
||||
int pfilter;
|
||||
int skip_band_floor;
|
||||
int tf_select;
|
||||
int alloc_trim;
|
||||
int alloc_boost[CELT_MAX_BANDS];
|
||||
int blocks; /* number of iMDCT blocks in the frame, depends on transient */
|
||||
int blocksize; /* size of each block */
|
||||
int silence; /* Frame is filled with silence */
|
||||
int anticollapse_needed; /* Whether to expect an anticollapse bit */
|
||||
int anticollapse; /* Encoded anticollapse bit */
|
||||
int intensity_stereo;
|
||||
int dual_stereo;
|
||||
int flushed;
|
||||
uint32_t seed;
|
||||
enum CeltSpread spread;
|
||||
|
||||
/* Encoder PF coeffs */
|
||||
int pf_octave;
|
||||
int pf_period;
|
||||
int pf_tapset;
|
||||
float pf_gain;
|
||||
|
||||
/* Bit allocation */
|
||||
int framebits;
|
||||
int remaining;
|
||||
int remaining2;
|
||||
int caps [CELT_MAX_BANDS];
|
||||
int fine_bits [CELT_MAX_BANDS];
|
||||
int fine_priority[CELT_MAX_BANDS];
|
||||
int pulses [CELT_MAX_BANDS];
|
||||
int tf_change [CELT_MAX_BANDS];
|
||||
} CeltFrame;
|
||||
|
||||
/* LCG for noise generation */
|
||||
static av_always_inline uint32_t celt_rng(CeltFrame *f)
|
||||
{
|
||||
f->seed = 1664525 * f->seed + 1013904223;
|
||||
return f->seed;
|
||||
}
|
||||
|
||||
static av_always_inline void celt_renormalize_vector(float *X, int N, float gain)
|
||||
{
|
||||
int i;
|
||||
float g = 1e-15f;
|
||||
for (i = 0; i < N; i++)
|
||||
g += X[i] * X[i];
|
||||
g = gain / sqrtf(g);
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
X[i] *= g;
|
||||
}
|
||||
|
||||
int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels,
|
||||
int apply_phase_inv);
|
||||
|
||||
void ff_celt_free(CeltFrame **f);
|
||||
|
||||
void ff_celt_flush(CeltFrame *f);
|
||||
|
||||
int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc, float **output,
|
||||
int coded_channels, int frame_size, int startband, int endband);
|
||||
|
||||
/* Encode or decode CELT bands */
|
||||
void ff_celt_quant_bands(CeltFrame *f, OpusRangeCoder *rc);
|
||||
|
||||
/* Encode or decode CELT bitallocation */
|
||||
void ff_celt_bitalloc(CeltFrame *f, OpusRangeCoder *rc, int encode);
|
||||
|
||||
#endif /* AVCODEC_OPUS_CELT_H */
|
||||
@@ -0,0 +1,785 @@
|
||||
/*
|
||||
* Opus decoder
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
*
|
||||
* 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
|
||||
* Opus decoder
|
||||
* @author Andrew D'Addesio, Anton Khirnov
|
||||
*
|
||||
* Codec homepage: http://opus-codec.org/
|
||||
* Specification: http://tools.ietf.org/html/rfc6716
|
||||
* Ogg Opus specification: https://tools.ietf.org/html/draft-ietf-codec-oggopus-03
|
||||
*
|
||||
* Ogg-contained .opus files can be produced with opus-tools:
|
||||
* http://git.xiph.org/?p=opus-tools.git
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/audio_fifo.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/ffmath.h"
|
||||
#include "libavutil/float_dsp.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
#include "libavutil/opt.h"
|
||||
|
||||
#include "libswresample/swresample.h"
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "decode.h"
|
||||
#include "opus.h"
|
||||
#include "tab.h"
|
||||
#include "celt.h"
|
||||
#include "parse.h"
|
||||
#include "rc.h"
|
||||
#include "silk.h"
|
||||
|
||||
static const uint16_t silk_frame_duration_ms[16] = {
|
||||
10, 20, 40, 60,
|
||||
10, 20, 40, 60,
|
||||
10, 20, 40, 60,
|
||||
10, 20,
|
||||
10, 20,
|
||||
};
|
||||
|
||||
/* number of samples of silence to feed to the resampler
|
||||
* at the beginning */
|
||||
static const int silk_resample_delay[] = {
|
||||
4, 8, 11, 11, 11
|
||||
};
|
||||
|
||||
typedef struct OpusStreamContext {
|
||||
AVCodecContext *avctx;
|
||||
int output_channels;
|
||||
|
||||
/* number of decoded samples for this stream */
|
||||
int decoded_samples;
|
||||
/* current output buffers for this stream */
|
||||
float *out[2];
|
||||
int out_size;
|
||||
/* Buffer with samples from this stream for synchronizing
|
||||
* the streams when they have different resampling delays */
|
||||
AVAudioFifo *sync_buffer;
|
||||
|
||||
OpusRangeCoder rc;
|
||||
OpusRangeCoder redundancy_rc;
|
||||
SilkContext *silk;
|
||||
CeltFrame *celt;
|
||||
AVFloatDSPContext *fdsp;
|
||||
|
||||
float silk_buf[2][960];
|
||||
float *silk_output[2];
|
||||
DECLARE_ALIGNED(32, float, celt_buf)[2][960];
|
||||
float *celt_output[2];
|
||||
|
||||
DECLARE_ALIGNED(32, float, redundancy_buf)[2][960];
|
||||
float *redundancy_output[2];
|
||||
|
||||
/* buffers for the next samples to be decoded */
|
||||
float *cur_out[2];
|
||||
int remaining_out_size;
|
||||
|
||||
float *out_dummy;
|
||||
int out_dummy_allocated_size;
|
||||
|
||||
SwrContext *swr;
|
||||
AVAudioFifo *celt_delay;
|
||||
int silk_samplerate;
|
||||
/* number of samples we still want to get from the resampler */
|
||||
int delayed_samples;
|
||||
|
||||
OpusPacket packet;
|
||||
|
||||
int redundancy_idx;
|
||||
} OpusStreamContext;
|
||||
|
||||
typedef struct OpusContext {
|
||||
AVClass *av_class;
|
||||
|
||||
struct OpusStreamContext *streams;
|
||||
int apply_phase_inv;
|
||||
|
||||
AVFloatDSPContext *fdsp;
|
||||
float gain;
|
||||
|
||||
OpusParseContext p;
|
||||
} OpusContext;
|
||||
|
||||
static int get_silk_samplerate(int config)
|
||||
{
|
||||
if (config < 4)
|
||||
return 8000;
|
||||
else if (config < 8)
|
||||
return 12000;
|
||||
return 16000;
|
||||
}
|
||||
|
||||
static void opus_fade(float *out,
|
||||
const float *in1, const float *in2,
|
||||
const float *window, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++)
|
||||
out[i] = in2[i] * window[i] + in1[i] * (1.0 - window[i]);
|
||||
}
|
||||
|
||||
static int opus_flush_resample(OpusStreamContext *s, int nb_samples)
|
||||
{
|
||||
int celt_size = av_audio_fifo_size(s->celt_delay);
|
||||
int ret, i;
|
||||
ret = swr_convert(s->swr,
|
||||
(uint8_t**)s->cur_out, nb_samples,
|
||||
NULL, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret != nb_samples) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Wrong number of flushed samples: %d\n",
|
||||
ret);
|
||||
return AVERROR_BUG;
|
||||
}
|
||||
|
||||
if (celt_size) {
|
||||
if (celt_size != nb_samples) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Wrong number of CELT delay samples.\n");
|
||||
return AVERROR_BUG;
|
||||
}
|
||||
av_audio_fifo_read(s->celt_delay, (void**)s->celt_output, nb_samples);
|
||||
for (i = 0; i < s->output_channels; i++) {
|
||||
s->fdsp->vector_fmac_scalar(s->cur_out[i],
|
||||
s->celt_output[i], 1.0,
|
||||
nb_samples);
|
||||
}
|
||||
}
|
||||
|
||||
if (s->redundancy_idx) {
|
||||
for (i = 0; i < s->output_channels; i++)
|
||||
opus_fade(s->cur_out[i], s->cur_out[i],
|
||||
s->redundancy_output[i] + 120 + s->redundancy_idx,
|
||||
ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx);
|
||||
s->redundancy_idx = 0;
|
||||
}
|
||||
|
||||
s->cur_out[0] += nb_samples;
|
||||
s->cur_out[1] += nb_samples;
|
||||
s->remaining_out_size -= nb_samples * sizeof(float);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opus_init_resample(OpusStreamContext *s)
|
||||
{
|
||||
static const float delay[16] = { 0.0 };
|
||||
const uint8_t *delayptr[2] = { (uint8_t*)delay, (uint8_t*)delay };
|
||||
int ret;
|
||||
|
||||
av_opt_set_int(s->swr, "in_sample_rate", s->silk_samplerate, 0);
|
||||
ret = swr_init(s->swr);
|
||||
if (ret < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Error opening the resampler.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = swr_convert(s->swr,
|
||||
NULL, 0,
|
||||
delayptr, silk_resample_delay[s->packet.bandwidth]);
|
||||
if (ret < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR,
|
||||
"Error feeding initial silence to the resampler.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opus_decode_redundancy(OpusStreamContext *s, const uint8_t *data, int size)
|
||||
{
|
||||
int ret = ff_opus_rc_dec_init(&s->redundancy_rc, data, size);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ff_opus_rc_dec_raw_init(&s->redundancy_rc, data + size, size);
|
||||
|
||||
ret = ff_celt_decode_frame(s->celt, &s->redundancy_rc,
|
||||
s->redundancy_output,
|
||||
s->packet.stereo + 1, 240,
|
||||
0, ff_celt_band_end[s->packet.bandwidth]);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Error decoding the redundancy frame.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int opus_decode_frame(OpusStreamContext *s, const uint8_t *data, int size)
|
||||
{
|
||||
int samples = s->packet.frame_duration;
|
||||
int redundancy = 0;
|
||||
int redundancy_size, redundancy_pos;
|
||||
int ret, i, consumed;
|
||||
int delayed_samples = s->delayed_samples;
|
||||
|
||||
ret = ff_opus_rc_dec_init(&s->rc, data, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* decode the silk frame */
|
||||
if (s->packet.mode == OPUS_MODE_SILK || s->packet.mode == OPUS_MODE_HYBRID) {
|
||||
if (!swr_is_initialized(s->swr)) {
|
||||
ret = opus_init_resample(s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
samples = ff_silk_decode_superframe(s->silk, &s->rc, s->silk_output,
|
||||
FFMIN(s->packet.bandwidth, OPUS_BANDWIDTH_WIDEBAND),
|
||||
s->packet.stereo + 1,
|
||||
silk_frame_duration_ms[s->packet.config]);
|
||||
if (samples < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Error decoding a SILK frame.\n");
|
||||
return samples;
|
||||
}
|
||||
samples = swr_convert(s->swr,
|
||||
(uint8_t**)s->cur_out, s->packet.frame_duration,
|
||||
(const uint8_t**)s->silk_output, samples);
|
||||
if (samples < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Error resampling SILK data.\n");
|
||||
return samples;
|
||||
}
|
||||
av_assert2((samples & 7) == 0);
|
||||
s->delayed_samples += s->packet.frame_duration - samples;
|
||||
} else
|
||||
ff_silk_flush(s->silk);
|
||||
|
||||
// decode redundancy information
|
||||
consumed = opus_rc_tell(&s->rc);
|
||||
if (s->packet.mode == OPUS_MODE_HYBRID && consumed + 37 <= size * 8)
|
||||
redundancy = ff_opus_rc_dec_log(&s->rc, 12);
|
||||
else if (s->packet.mode == OPUS_MODE_SILK && consumed + 17 <= size * 8)
|
||||
redundancy = 1;
|
||||
|
||||
if (redundancy) {
|
||||
redundancy_pos = ff_opus_rc_dec_log(&s->rc, 1);
|
||||
|
||||
if (s->packet.mode == OPUS_MODE_HYBRID)
|
||||
redundancy_size = ff_opus_rc_dec_uint(&s->rc, 256) + 2;
|
||||
else
|
||||
redundancy_size = size - (consumed + 7) / 8;
|
||||
size -= redundancy_size;
|
||||
if (size < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Invalid redundancy frame size.\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (redundancy_pos) {
|
||||
ret = opus_decode_redundancy(s, data + size, redundancy_size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ff_celt_flush(s->celt);
|
||||
}
|
||||
}
|
||||
|
||||
/* decode the CELT frame */
|
||||
if (s->packet.mode == OPUS_MODE_CELT || s->packet.mode == OPUS_MODE_HYBRID) {
|
||||
float *out_tmp[2] = { s->cur_out[0], s->cur_out[1] };
|
||||
float **dst = (s->packet.mode == OPUS_MODE_CELT) ?
|
||||
out_tmp : s->celt_output;
|
||||
int celt_output_samples = samples;
|
||||
int delay_samples = av_audio_fifo_size(s->celt_delay);
|
||||
|
||||
if (delay_samples) {
|
||||
if (s->packet.mode == OPUS_MODE_HYBRID) {
|
||||
av_audio_fifo_read(s->celt_delay, (void**)s->celt_output, delay_samples);
|
||||
|
||||
for (i = 0; i < s->output_channels; i++) {
|
||||
s->fdsp->vector_fmac_scalar(out_tmp[i], s->celt_output[i], 1.0,
|
||||
delay_samples);
|
||||
out_tmp[i] += delay_samples;
|
||||
}
|
||||
celt_output_samples -= delay_samples;
|
||||
} else {
|
||||
av_log(s->avctx, AV_LOG_WARNING,
|
||||
"Spurious CELT delay samples present.\n");
|
||||
av_audio_fifo_reset(s->celt_delay);
|
||||
if (s->avctx->err_recognition & AV_EF_EXPLODE)
|
||||
return AVERROR_BUG;
|
||||
}
|
||||
}
|
||||
|
||||
ff_opus_rc_dec_raw_init(&s->rc, data + size, size);
|
||||
|
||||
ret = ff_celt_decode_frame(s->celt, &s->rc, dst,
|
||||
s->packet.stereo + 1,
|
||||
s->packet.frame_duration,
|
||||
(s->packet.mode == OPUS_MODE_HYBRID) ? 17 : 0,
|
||||
ff_celt_band_end[s->packet.bandwidth]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (s->packet.mode == OPUS_MODE_HYBRID) {
|
||||
int celt_delay = s->packet.frame_duration - celt_output_samples;
|
||||
void *delaybuf[2] = { s->celt_output[0] + celt_output_samples,
|
||||
s->celt_output[1] + celt_output_samples };
|
||||
|
||||
for (i = 0; i < s->output_channels; i++) {
|
||||
s->fdsp->vector_fmac_scalar(out_tmp[i],
|
||||
s->celt_output[i], 1.0,
|
||||
celt_output_samples);
|
||||
}
|
||||
|
||||
ret = av_audio_fifo_write(s->celt_delay, delaybuf, celt_delay);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
} else
|
||||
ff_celt_flush(s->celt);
|
||||
|
||||
if (s->redundancy_idx) {
|
||||
for (i = 0; i < s->output_channels; i++)
|
||||
opus_fade(s->cur_out[i], s->cur_out[i],
|
||||
s->redundancy_output[i] + 120 + s->redundancy_idx,
|
||||
ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx);
|
||||
s->redundancy_idx = 0;
|
||||
}
|
||||
if (redundancy) {
|
||||
if (!redundancy_pos) {
|
||||
ff_celt_flush(s->celt);
|
||||
ret = opus_decode_redundancy(s, data + size, redundancy_size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < s->output_channels; i++) {
|
||||
opus_fade(s->cur_out[i] + samples - 120 + delayed_samples,
|
||||
s->cur_out[i] + samples - 120 + delayed_samples,
|
||||
s->redundancy_output[i] + 120,
|
||||
ff_celt_window2, 120 - delayed_samples);
|
||||
if (delayed_samples)
|
||||
s->redundancy_idx = 120 - delayed_samples;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < s->output_channels; i++) {
|
||||
memcpy(s->cur_out[i] + delayed_samples, s->redundancy_output[i], 120 * sizeof(float));
|
||||
opus_fade(s->cur_out[i] + 120 + delayed_samples,
|
||||
s->redundancy_output[i] + 120,
|
||||
s->cur_out[i] + 120 + delayed_samples,
|
||||
ff_celt_window2, 120);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
static int opus_decode_subpacket(OpusStreamContext *s, const uint8_t *buf)
|
||||
{
|
||||
int output_samples = 0;
|
||||
int flush_needed = 0;
|
||||
int i, j, ret;
|
||||
|
||||
s->cur_out[0] = s->out[0];
|
||||
s->cur_out[1] = s->out[1];
|
||||
s->remaining_out_size = s->out_size;
|
||||
|
||||
/* check if we need to flush the resampler */
|
||||
if (swr_is_initialized(s->swr)) {
|
||||
if (buf) {
|
||||
int64_t cur_samplerate;
|
||||
av_opt_get_int(s->swr, "in_sample_rate", 0, &cur_samplerate);
|
||||
flush_needed = (s->packet.mode == OPUS_MODE_CELT) || (cur_samplerate != s->silk_samplerate);
|
||||
} else {
|
||||
flush_needed = !!s->delayed_samples;
|
||||
}
|
||||
}
|
||||
|
||||
if (!buf && !flush_needed)
|
||||
return 0;
|
||||
|
||||
/* use dummy output buffers if the channel is not mapped to anything */
|
||||
if (!s->cur_out[0] ||
|
||||
(s->output_channels == 2 && !s->cur_out[1])) {
|
||||
av_fast_malloc(&s->out_dummy, &s->out_dummy_allocated_size,
|
||||
s->remaining_out_size);
|
||||
if (!s->out_dummy)
|
||||
return AVERROR(ENOMEM);
|
||||
if (!s->cur_out[0])
|
||||
s->cur_out[0] = s->out_dummy;
|
||||
if (!s->cur_out[1])
|
||||
s->cur_out[1] = s->out_dummy;
|
||||
}
|
||||
|
||||
/* flush the resampler if necessary */
|
||||
if (flush_needed) {
|
||||
ret = opus_flush_resample(s, s->delayed_samples);
|
||||
if (ret < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Error flushing the resampler.\n");
|
||||
return ret;
|
||||
}
|
||||
swr_close(s->swr);
|
||||
output_samples += s->delayed_samples;
|
||||
s->delayed_samples = 0;
|
||||
|
||||
if (!buf)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* decode all the frames in the packet */
|
||||
for (i = 0; i < s->packet.frame_count; i++) {
|
||||
int size = s->packet.frame_size[i];
|
||||
int samples = opus_decode_frame(s, buf + s->packet.frame_offset[i], size);
|
||||
|
||||
if (samples < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Error decoding an Opus frame.\n");
|
||||
if (s->avctx->err_recognition & AV_EF_EXPLODE)
|
||||
return samples;
|
||||
|
||||
for (j = 0; j < s->output_channels; j++)
|
||||
memset(s->cur_out[j], 0, s->packet.frame_duration * sizeof(float));
|
||||
samples = s->packet.frame_duration;
|
||||
}
|
||||
output_samples += samples;
|
||||
|
||||
for (j = 0; j < s->output_channels; j++)
|
||||
s->cur_out[j] += samples;
|
||||
s->remaining_out_size -= samples * sizeof(float);
|
||||
}
|
||||
|
||||
finish:
|
||||
s->cur_out[0] = s->cur_out[1] = NULL;
|
||||
s->remaining_out_size = 0;
|
||||
|
||||
return output_samples;
|
||||
}
|
||||
|
||||
static int opus_decode_packet(AVCodecContext *avctx, AVFrame *frame,
|
||||
int *got_frame_ptr, AVPacket *avpkt)
|
||||
{
|
||||
OpusContext *c = avctx->priv_data;
|
||||
const uint8_t *buf = avpkt->data;
|
||||
int buf_size = avpkt->size;
|
||||
int coded_samples = 0;
|
||||
int decoded_samples = INT_MAX;
|
||||
int delayed_samples = 0;
|
||||
int i, ret;
|
||||
|
||||
/* calculate the number of delayed samples */
|
||||
for (int i = 0; i < c->p.nb_streams; i++) {
|
||||
OpusStreamContext *s = &c->streams[i];
|
||||
s->out[0] =
|
||||
s->out[1] = NULL;
|
||||
int fifo_samples = av_audio_fifo_size(s->sync_buffer);
|
||||
delayed_samples = FFMAX(delayed_samples,
|
||||
s->delayed_samples + fifo_samples);
|
||||
}
|
||||
|
||||
/* decode the header of the first sub-packet to find out the sample count */
|
||||
if (buf) {
|
||||
OpusPacket *pkt = &c->streams[0].packet;
|
||||
ret = ff_opus_parse_packet(pkt, buf, buf_size, c->p.nb_streams > 1);
|
||||
if (ret < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error parsing the packet header.\n");
|
||||
return ret;
|
||||
}
|
||||
coded_samples += pkt->frame_count * pkt->frame_duration;
|
||||
c->streams[0].silk_samplerate = get_silk_samplerate(pkt->config);
|
||||
}
|
||||
|
||||
frame->nb_samples = coded_samples + delayed_samples;
|
||||
|
||||
/* no input or buffered data => nothing to do */
|
||||
if (!frame->nb_samples) {
|
||||
*got_frame_ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* setup the data buffers */
|
||||
ret = ff_get_buffer(avctx, frame, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
frame->nb_samples = 0;
|
||||
|
||||
for (i = 0; i < avctx->ch_layout.nb_channels; i++) {
|
||||
ChannelMap *map = &c->p.channel_maps[i];
|
||||
if (!map->copy)
|
||||
c->streams[map->stream_idx].out[map->channel_idx] = (float*)frame->extended_data[i];
|
||||
}
|
||||
|
||||
/* read the data from the sync buffers */
|
||||
for (int i = 0; i < c->p.nb_streams; i++) {
|
||||
OpusStreamContext *s = &c->streams[i];
|
||||
float **out = s->out;
|
||||
int sync_size = av_audio_fifo_size(s->sync_buffer);
|
||||
|
||||
float sync_dummy[32];
|
||||
int out_dummy = (!out[0]) | ((!out[1]) << 1);
|
||||
|
||||
if (!out[0])
|
||||
out[0] = sync_dummy;
|
||||
if (!out[1])
|
||||
out[1] = sync_dummy;
|
||||
if (out_dummy && sync_size > FF_ARRAY_ELEMS(sync_dummy))
|
||||
return AVERROR_BUG;
|
||||
|
||||
ret = av_audio_fifo_read(s->sync_buffer, (void**)out, sync_size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (out_dummy & 1)
|
||||
out[0] = NULL;
|
||||
else
|
||||
out[0] += ret;
|
||||
if (out_dummy & 2)
|
||||
out[1] = NULL;
|
||||
else
|
||||
out[1] += ret;
|
||||
|
||||
s->out_size = frame->linesize[0] - ret * sizeof(float);
|
||||
}
|
||||
|
||||
/* decode each sub-packet */
|
||||
for (int i = 0; i < c->p.nb_streams; i++) {
|
||||
OpusStreamContext *s = &c->streams[i];
|
||||
|
||||
if (i && buf) {
|
||||
ret = ff_opus_parse_packet(&s->packet, buf, buf_size, i != c->p.nb_streams - 1);
|
||||
if (ret < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error parsing the packet header.\n");
|
||||
return ret;
|
||||
}
|
||||
if (coded_samples != s->packet.frame_count * s->packet.frame_duration) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Mismatching coded sample count in substream %d.\n", i);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
s->silk_samplerate = get_silk_samplerate(s->packet.config);
|
||||
}
|
||||
|
||||
ret = opus_decode_subpacket(&c->streams[i], buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
s->decoded_samples = ret;
|
||||
decoded_samples = FFMIN(decoded_samples, ret);
|
||||
|
||||
if (!buf)
|
||||
continue;
|
||||
|
||||
buf += s->packet.packet_size;
|
||||
buf_size -= s->packet.packet_size;
|
||||
}
|
||||
|
||||
/* buffer the extra samples */
|
||||
for (int i = 0; i < c->p.nb_streams; i++) {
|
||||
OpusStreamContext *s = &c->streams[i];
|
||||
int buffer_samples = s->decoded_samples - decoded_samples;
|
||||
if (buffer_samples) {
|
||||
float *buf[2] = { s->out[0] ? s->out[0] : (float*)frame->extended_data[0],
|
||||
s->out[1] ? s->out[1] : (float*)frame->extended_data[0] };
|
||||
buf[0] += decoded_samples;
|
||||
buf[1] += decoded_samples;
|
||||
ret = av_audio_fifo_write(s->sync_buffer, (void**)buf, buffer_samples);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < avctx->ch_layout.nb_channels; i++) {
|
||||
ChannelMap *map = &c->p.channel_maps[i];
|
||||
|
||||
/* handle copied channels */
|
||||
if (map->copy) {
|
||||
memcpy(frame->extended_data[i],
|
||||
frame->extended_data[map->copy_idx],
|
||||
frame->linesize[0]);
|
||||
} else if (map->silence) {
|
||||
memset(frame->extended_data[i], 0, frame->linesize[0]);
|
||||
}
|
||||
|
||||
if (c->p.gain_i && decoded_samples > 0) {
|
||||
c->fdsp->vector_fmul_scalar((float*)frame->extended_data[i],
|
||||
(float*)frame->extended_data[i],
|
||||
c->gain, FFALIGN(decoded_samples, 8));
|
||||
}
|
||||
}
|
||||
|
||||
frame->nb_samples = decoded_samples;
|
||||
*got_frame_ptr = !!decoded_samples;
|
||||
|
||||
return avpkt->size;
|
||||
}
|
||||
|
||||
static av_cold void opus_decode_flush(AVCodecContext *ctx)
|
||||
{
|
||||
OpusContext *c = ctx->priv_data;
|
||||
|
||||
for (int i = 0; i < c->p.nb_streams; i++) {
|
||||
OpusStreamContext *s = &c->streams[i];
|
||||
|
||||
memset(&s->packet, 0, sizeof(s->packet));
|
||||
s->delayed_samples = 0;
|
||||
|
||||
av_audio_fifo_reset(s->celt_delay);
|
||||
swr_close(s->swr);
|
||||
|
||||
av_audio_fifo_reset(s->sync_buffer);
|
||||
|
||||
ff_silk_flush(s->silk);
|
||||
ff_celt_flush(s->celt);
|
||||
}
|
||||
}
|
||||
|
||||
static av_cold int opus_decode_close(AVCodecContext *avctx)
|
||||
{
|
||||
OpusContext *c = avctx->priv_data;
|
||||
|
||||
for (int i = 0; i < c->p.nb_streams; i++) {
|
||||
OpusStreamContext *s = &c->streams[i];
|
||||
|
||||
ff_silk_free(&s->silk);
|
||||
ff_celt_free(&s->celt);
|
||||
|
||||
av_freep(&s->out_dummy);
|
||||
s->out_dummy_allocated_size = 0;
|
||||
|
||||
av_audio_fifo_free(s->sync_buffer);
|
||||
av_audio_fifo_free(s->celt_delay);
|
||||
swr_free(&s->swr);
|
||||
}
|
||||
|
||||
av_freep(&c->streams);
|
||||
|
||||
c->p.nb_streams = 0;
|
||||
|
||||
av_freep(&c->p.channel_maps);
|
||||
av_freep(&c->fdsp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_cold int opus_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
OpusContext *c = avctx->priv_data;
|
||||
int ret;
|
||||
|
||||
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
||||
avctx->sample_rate = 48000;
|
||||
|
||||
c->fdsp = avpriv_float_dsp_alloc(0);
|
||||
if (!c->fdsp)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
/* find out the channel configuration */
|
||||
ret = ff_opus_parse_extradata(avctx, &c->p);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (c->p.gain_i)
|
||||
c->gain = ff_exp10(c->p.gain_i / (20.0 * 256));
|
||||
|
||||
/* allocate and init each independent decoder */
|
||||
c->streams = av_calloc(c->p.nb_streams, sizeof(*c->streams));
|
||||
if (!c->streams) {
|
||||
c->p.nb_streams = 0;
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
for (int i = 0; i < c->p.nb_streams; i++) {
|
||||
OpusStreamContext *s = &c->streams[i];
|
||||
AVChannelLayout layout;
|
||||
|
||||
s->output_channels = (i < c->p.nb_stereo_streams) ? 2 : 1;
|
||||
|
||||
s->avctx = avctx;
|
||||
|
||||
for (int j = 0; j < s->output_channels; j++) {
|
||||
s->silk_output[j] = s->silk_buf[j];
|
||||
s->celt_output[j] = s->celt_buf[j];
|
||||
s->redundancy_output[j] = s->redundancy_buf[j];
|
||||
}
|
||||
|
||||
s->fdsp = c->fdsp;
|
||||
|
||||
s->swr =swr_alloc();
|
||||
if (!s->swr)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
layout = (s->output_channels == 1) ? (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO :
|
||||
(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
|
||||
av_opt_set_int(s->swr, "in_sample_fmt", avctx->sample_fmt, 0);
|
||||
av_opt_set_int(s->swr, "out_sample_fmt", avctx->sample_fmt, 0);
|
||||
av_opt_set_chlayout(s->swr, "in_chlayout", &layout, 0);
|
||||
av_opt_set_chlayout(s->swr, "out_chlayout", &layout, 0);
|
||||
av_opt_set_int(s->swr, "out_sample_rate", avctx->sample_rate, 0);
|
||||
av_opt_set_int(s->swr, "filter_size", 16, 0);
|
||||
|
||||
ret = ff_silk_init(avctx, &s->silk, s->output_channels);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ff_celt_init(avctx, &s->celt, s->output_channels, c->apply_phase_inv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
s->celt_delay = av_audio_fifo_alloc(avctx->sample_fmt,
|
||||
s->output_channels, 1024);
|
||||
if (!s->celt_delay)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
s->sync_buffer = av_audio_fifo_alloc(avctx->sample_fmt,
|
||||
s->output_channels, 32);
|
||||
if (!s->sync_buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define OFFSET(x) offsetof(OpusContext, x)
|
||||
#define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM
|
||||
static const AVOption opus_options[] = {
|
||||
{ "apply_phase_inv", "Apply intensity stereo phase inversion", OFFSET(apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AD },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const AVClass opus_class = {
|
||||
.class_name = "Opus Decoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = opus_options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
const FFCodec ff_opus_decoder = {
|
||||
.p.name = "opus",
|
||||
CODEC_LONG_NAME("Opus"),
|
||||
.p.priv_class = &opus_class,
|
||||
.p.type = AVMEDIA_TYPE_AUDIO,
|
||||
.p.id = AV_CODEC_ID_OPUS,
|
||||
.priv_data_size = sizeof(OpusContext),
|
||||
.init = opus_decode_init,
|
||||
.close = opus_decode_close,
|
||||
FF_CODEC_DECODE_CB(opus_decode_packet),
|
||||
.flush = opus_decode_flush,
|
||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
};
|
||||
@@ -0,0 +1,589 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
* Copyright (c) 2016 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* Opus CELT decoder
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include "libavutil/mem.h"
|
||||
#include "celt.h"
|
||||
#include "tab.h"
|
||||
#include "pvq.h"
|
||||
|
||||
/* Use the 2D z-transform to apply prediction in both the time domain (alpha)
|
||||
* and the frequency domain (beta) */
|
||||
static void celt_decode_coarse_energy(CeltFrame *f, OpusRangeCoder *rc)
|
||||
{
|
||||
int i, j;
|
||||
float prev[2] = { 0 };
|
||||
float alpha = ff_celt_alpha_coef[f->size];
|
||||
float beta = ff_celt_beta_coef[f->size];
|
||||
const uint8_t *model = ff_celt_coarse_energy_dist[f->size][0];
|
||||
|
||||
/* intra frame */
|
||||
if (opus_rc_tell(rc) + 3 <= f->framebits && ff_opus_rc_dec_log(rc, 3)) {
|
||||
alpha = 0.0f;
|
||||
beta = 1.0f - (4915.0f/32768.0f);
|
||||
model = ff_celt_coarse_energy_dist[f->size][1];
|
||||
}
|
||||
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
for (j = 0; j < f->channels; j++) {
|
||||
CeltBlock *block = &f->block[j];
|
||||
float value;
|
||||
int available;
|
||||
|
||||
if (i < f->start_band || i >= f->end_band) {
|
||||
block->energy[i] = 0.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
available = f->framebits - opus_rc_tell(rc);
|
||||
if (available >= 15) {
|
||||
/* decode using a Laplace distribution */
|
||||
int k = FFMIN(i, 20) << 1;
|
||||
value = ff_opus_rc_dec_laplace(rc, model[k] << 7, model[k+1] << 6);
|
||||
} else if (available >= 2) {
|
||||
int x = ff_opus_rc_dec_cdf(rc, ff_celt_model_energy_small);
|
||||
value = (x>>1) ^ -(x&1);
|
||||
} else if (available >= 1) {
|
||||
value = -(float)ff_opus_rc_dec_log(rc, 1);
|
||||
} else value = -1;
|
||||
|
||||
block->energy[i] = FFMAX(-9.0f, block->energy[i]) * alpha + prev[j] + value;
|
||||
prev[j] += beta * value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_decode_fine_energy(CeltFrame *f, OpusRangeCoder *rc)
|
||||
{
|
||||
int i;
|
||||
for (i = f->start_band; i < f->end_band; i++) {
|
||||
int j;
|
||||
if (!f->fine_bits[i])
|
||||
continue;
|
||||
|
||||
for (j = 0; j < f->channels; j++) {
|
||||
CeltBlock *block = &f->block[j];
|
||||
int q2;
|
||||
float offset;
|
||||
q2 = ff_opus_rc_get_raw(rc, f->fine_bits[i]);
|
||||
offset = (q2 + 0.5f) * (1 << (14 - f->fine_bits[i])) / 16384.0f - 0.5f;
|
||||
block->energy[i] += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_decode_final_energy(CeltFrame *f, OpusRangeCoder *rc)
|
||||
{
|
||||
int priority, i, j;
|
||||
int bits_left = f->framebits - opus_rc_tell(rc);
|
||||
|
||||
for (priority = 0; priority < 2; priority++) {
|
||||
for (i = f->start_band; i < f->end_band && bits_left >= f->channels; i++) {
|
||||
if (f->fine_priority[i] != priority || f->fine_bits[i] >= CELT_MAX_FINE_BITS)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < f->channels; j++) {
|
||||
int q2;
|
||||
float offset;
|
||||
q2 = ff_opus_rc_get_raw(rc, 1);
|
||||
offset = (q2 - 0.5f) * (1 << (14 - f->fine_bits[i] - 1)) / 16384.0f;
|
||||
f->block[j].energy[i] += offset;
|
||||
bits_left--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_decode_tf_changes(CeltFrame *f, OpusRangeCoder *rc)
|
||||
{
|
||||
int i, diff = 0, tf_select = 0, tf_changed = 0, tf_select_bit;
|
||||
int consumed, bits = f->transient ? 2 : 4;
|
||||
|
||||
consumed = opus_rc_tell(rc);
|
||||
tf_select_bit = (f->size != 0 && consumed+bits+1 <= f->framebits);
|
||||
|
||||
for (i = f->start_band; i < f->end_band; i++) {
|
||||
if (consumed+bits+tf_select_bit <= f->framebits) {
|
||||
diff ^= ff_opus_rc_dec_log(rc, bits);
|
||||
consumed = opus_rc_tell(rc);
|
||||
tf_changed |= diff;
|
||||
}
|
||||
f->tf_change[i] = diff;
|
||||
bits = f->transient ? 4 : 5;
|
||||
}
|
||||
|
||||
if (tf_select_bit && ff_celt_tf_select[f->size][f->transient][0][tf_changed] !=
|
||||
ff_celt_tf_select[f->size][f->transient][1][tf_changed])
|
||||
tf_select = ff_opus_rc_dec_log(rc, 1);
|
||||
|
||||
for (i = f->start_band; i < f->end_band; i++) {
|
||||
f->tf_change[i] = ff_celt_tf_select[f->size][f->transient][tf_select][f->tf_change[i]];
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_denormalize(CeltFrame *f, CeltBlock *block, float *data)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = f->start_band; i < f->end_band; i++) {
|
||||
float *dst = data + (ff_celt_freq_bands[i] << f->size);
|
||||
float log_norm = block->energy[i] + ff_celt_mean_energy[i];
|
||||
float norm = exp2f(FFMIN(log_norm, 32.0f));
|
||||
|
||||
for (j = 0; j < ff_celt_freq_range[i] << f->size; j++)
|
||||
dst[j] *= norm;
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_postfilter_apply_transition(CeltBlock *block, float *data)
|
||||
{
|
||||
const int T0 = block->pf_period_old;
|
||||
const int T1 = block->pf_period;
|
||||
|
||||
float g00, g01, g02;
|
||||
float g10, g11, g12;
|
||||
|
||||
float x0, x1, x2, x3, x4;
|
||||
|
||||
int i;
|
||||
|
||||
if (block->pf_gains[0] == 0.0 &&
|
||||
block->pf_gains_old[0] == 0.0)
|
||||
return;
|
||||
|
||||
g00 = block->pf_gains_old[0];
|
||||
g01 = block->pf_gains_old[1];
|
||||
g02 = block->pf_gains_old[2];
|
||||
g10 = block->pf_gains[0];
|
||||
g11 = block->pf_gains[1];
|
||||
g12 = block->pf_gains[2];
|
||||
|
||||
x1 = data[-T1 + 1];
|
||||
x2 = data[-T1];
|
||||
x3 = data[-T1 - 1];
|
||||
x4 = data[-T1 - 2];
|
||||
|
||||
for (i = 0; i < CELT_OVERLAP; i++) {
|
||||
float w = ff_celt_window2[i];
|
||||
x0 = data[i - T1 + 2];
|
||||
|
||||
data[i] += (1.0 - w) * g00 * data[i - T0] +
|
||||
(1.0 - w) * g01 * (data[i - T0 - 1] + data[i - T0 + 1]) +
|
||||
(1.0 - w) * g02 * (data[i - T0 - 2] + data[i - T0 + 2]) +
|
||||
w * g10 * x2 +
|
||||
w * g11 * (x1 + x3) +
|
||||
w * g12 * (x0 + x4);
|
||||
x4 = x3;
|
||||
x3 = x2;
|
||||
x2 = x1;
|
||||
x1 = x0;
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_postfilter(CeltFrame *f, CeltBlock *block)
|
||||
{
|
||||
int len = f->blocksize * f->blocks;
|
||||
const int filter_len = len - 2 * CELT_OVERLAP;
|
||||
|
||||
celt_postfilter_apply_transition(block, block->buf + 1024);
|
||||
|
||||
block->pf_period_old = block->pf_period;
|
||||
memcpy(block->pf_gains_old, block->pf_gains, sizeof(block->pf_gains));
|
||||
|
||||
block->pf_period = block->pf_period_new;
|
||||
memcpy(block->pf_gains, block->pf_gains_new, sizeof(block->pf_gains));
|
||||
|
||||
if (len > CELT_OVERLAP) {
|
||||
celt_postfilter_apply_transition(block, block->buf + 1024 + CELT_OVERLAP);
|
||||
|
||||
if (block->pf_gains[0] > FLT_EPSILON && filter_len > 0)
|
||||
f->opusdsp.postfilter(block->buf + 1024 + 2 * CELT_OVERLAP,
|
||||
block->pf_period, block->pf_gains,
|
||||
filter_len);
|
||||
|
||||
block->pf_period_old = block->pf_period;
|
||||
memcpy(block->pf_gains_old, block->pf_gains, sizeof(block->pf_gains));
|
||||
}
|
||||
|
||||
memmove(block->buf, block->buf + len, (1024 + CELT_OVERLAP / 2) * sizeof(float));
|
||||
}
|
||||
|
||||
static int parse_postfilter(CeltFrame *f, OpusRangeCoder *rc, int consumed)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(f->block[0].pf_gains_new, 0, sizeof(f->block[0].pf_gains_new));
|
||||
memset(f->block[1].pf_gains_new, 0, sizeof(f->block[1].pf_gains_new));
|
||||
|
||||
if (f->start_band == 0 && consumed + 16 <= f->framebits) {
|
||||
int has_postfilter = ff_opus_rc_dec_log(rc, 1);
|
||||
if (has_postfilter) {
|
||||
float gain;
|
||||
int tapset, octave, period;
|
||||
|
||||
octave = ff_opus_rc_dec_uint(rc, 6);
|
||||
period = (16 << octave) + ff_opus_rc_get_raw(rc, 4 + octave) - 1;
|
||||
gain = 0.09375f * (ff_opus_rc_get_raw(rc, 3) + 1);
|
||||
tapset = (opus_rc_tell(rc) + 2 <= f->framebits) ?
|
||||
ff_opus_rc_dec_cdf(rc, ff_celt_model_tapset) : 0;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
CeltBlock *block = &f->block[i];
|
||||
|
||||
block->pf_period_new = FFMAX(period, CELT_POSTFILTER_MINPERIOD);
|
||||
block->pf_gains_new[0] = gain * ff_celt_postfilter_taps[tapset][0];
|
||||
block->pf_gains_new[1] = gain * ff_celt_postfilter_taps[tapset][1];
|
||||
block->pf_gains_new[2] = gain * ff_celt_postfilter_taps[tapset][2];
|
||||
}
|
||||
}
|
||||
|
||||
consumed = opus_rc_tell(rc);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void process_anticollapse(CeltFrame *f, CeltBlock *block, float *X)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
for (i = f->start_band; i < f->end_band; i++) {
|
||||
int renormalize = 0;
|
||||
float *xptr;
|
||||
float prev[2];
|
||||
float Ediff, r;
|
||||
float thresh, sqrt_1;
|
||||
int depth;
|
||||
|
||||
/* depth in 1/8 bits */
|
||||
depth = (1 + f->pulses[i]) / (ff_celt_freq_range[i] << f->size);
|
||||
thresh = exp2f(-1.0 - 0.125f * depth);
|
||||
sqrt_1 = 1.0f / sqrtf(ff_celt_freq_range[i] << f->size);
|
||||
|
||||
xptr = X + (ff_celt_freq_bands[i] << f->size);
|
||||
|
||||
prev[0] = block->prev_energy[0][i];
|
||||
prev[1] = block->prev_energy[1][i];
|
||||
if (f->channels == 1) {
|
||||
CeltBlock *block1 = &f->block[1];
|
||||
|
||||
prev[0] = FFMAX(prev[0], block1->prev_energy[0][i]);
|
||||
prev[1] = FFMAX(prev[1], block1->prev_energy[1][i]);
|
||||
}
|
||||
Ediff = block->energy[i] - FFMIN(prev[0], prev[1]);
|
||||
Ediff = FFMAX(0, Ediff);
|
||||
|
||||
/* r needs to be multiplied by 2 or 2*sqrt(2) depending on LM because
|
||||
short blocks don't have the same energy as long */
|
||||
r = exp2f(1 - Ediff);
|
||||
if (f->size == 3)
|
||||
r *= M_SQRT2;
|
||||
r = FFMIN(thresh, r) * sqrt_1;
|
||||
for (k = 0; k < 1 << f->size; k++) {
|
||||
/* Detect collapse */
|
||||
if (!(block->collapse_masks[i] & 1 << k)) {
|
||||
/* Fill with noise */
|
||||
for (j = 0; j < ff_celt_freq_range[i]; j++)
|
||||
xptr[(j << f->size) + k] = (celt_rng(f) & 0x8000) ? r : -r;
|
||||
renormalize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We just added some energy, so we need to renormalize */
|
||||
if (renormalize)
|
||||
celt_renormalize_vector(xptr, ff_celt_freq_range[i] << f->size, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
int ff_celt_decode_frame(CeltFrame *f, OpusRangeCoder *rc,
|
||||
float **output, int channels, int frame_size,
|
||||
int start_band, int end_band)
|
||||
{
|
||||
int i, j, downmix = 0;
|
||||
int consumed; // bits of entropy consumed thus far for this frame
|
||||
AVTXContext *imdct;
|
||||
av_tx_fn imdct_fn;
|
||||
|
||||
if (channels != 1 && channels != 2) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "Invalid number of coded channels: %d\n",
|
||||
channels);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (start_band < 0 || start_band > end_band || end_band > CELT_MAX_BANDS) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "Invalid start/end band: %d %d\n",
|
||||
start_band, end_band);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
f->silence = 0;
|
||||
f->transient = 0;
|
||||
f->anticollapse = 0;
|
||||
f->flushed = 0;
|
||||
f->channels = channels;
|
||||
f->start_band = start_band;
|
||||
f->end_band = end_band;
|
||||
f->framebits = rc->rb.bytes * 8;
|
||||
|
||||
f->size = av_log2(frame_size / CELT_SHORT_BLOCKSIZE);
|
||||
if (f->size > CELT_MAX_LOG_BLOCKS ||
|
||||
frame_size != CELT_SHORT_BLOCKSIZE * (1 << f->size)) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "Invalid CELT frame size: %d\n",
|
||||
frame_size);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (!f->output_channels)
|
||||
f->output_channels = channels;
|
||||
|
||||
for (i = 0; i < f->channels; i++) {
|
||||
memset(f->block[i].coeffs, 0, sizeof(f->block[i].coeffs));
|
||||
memset(f->block[i].collapse_masks, 0, sizeof(f->block[i].collapse_masks));
|
||||
}
|
||||
|
||||
consumed = opus_rc_tell(rc);
|
||||
|
||||
/* obtain silence flag */
|
||||
if (consumed >= f->framebits)
|
||||
f->silence = 1;
|
||||
else if (consumed == 1)
|
||||
f->silence = ff_opus_rc_dec_log(rc, 15);
|
||||
|
||||
|
||||
if (f->silence) {
|
||||
consumed = f->framebits;
|
||||
rc->total_bits += f->framebits - opus_rc_tell(rc);
|
||||
}
|
||||
|
||||
/* obtain post-filter options */
|
||||
consumed = parse_postfilter(f, rc, consumed);
|
||||
|
||||
/* obtain transient flag */
|
||||
if (f->size != 0 && consumed+3 <= f->framebits)
|
||||
f->transient = ff_opus_rc_dec_log(rc, 3);
|
||||
|
||||
f->blocks = f->transient ? 1 << f->size : 1;
|
||||
f->blocksize = frame_size / f->blocks;
|
||||
|
||||
imdct = f->tx[f->transient ? 0 : f->size];
|
||||
imdct_fn = f->tx_fn[f->transient ? 0 : f->size];
|
||||
|
||||
if (channels == 1) {
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++)
|
||||
f->block[0].energy[i] = FFMAX(f->block[0].energy[i], f->block[1].energy[i]);
|
||||
}
|
||||
|
||||
celt_decode_coarse_energy(f, rc);
|
||||
celt_decode_tf_changes (f, rc);
|
||||
ff_celt_bitalloc (f, rc, 0);
|
||||
celt_decode_fine_energy (f, rc);
|
||||
ff_celt_quant_bands (f, rc);
|
||||
|
||||
if (f->anticollapse_needed)
|
||||
f->anticollapse = ff_opus_rc_get_raw(rc, 1);
|
||||
|
||||
celt_decode_final_energy(f, rc);
|
||||
|
||||
/* apply anti-collapse processing and denormalization to
|
||||
* each coded channel */
|
||||
for (i = 0; i < f->channels; i++) {
|
||||
CeltBlock *block = &f->block[i];
|
||||
|
||||
if (f->anticollapse)
|
||||
process_anticollapse(f, block, f->block[i].coeffs);
|
||||
|
||||
celt_denormalize(f, block, f->block[i].coeffs);
|
||||
}
|
||||
|
||||
/* stereo -> mono downmix */
|
||||
if (f->output_channels < f->channels) {
|
||||
f->dsp->vector_fmac_scalar(f->block[0].coeffs, f->block[1].coeffs, 1.0, FFALIGN(frame_size, 16));
|
||||
downmix = 1;
|
||||
} else if (f->output_channels > f->channels)
|
||||
memcpy(f->block[1].coeffs, f->block[0].coeffs, frame_size * sizeof(float));
|
||||
|
||||
if (f->silence) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
CeltBlock *block = &f->block[i];
|
||||
|
||||
for (j = 0; j < FF_ARRAY_ELEMS(block->energy); j++)
|
||||
block->energy[j] = CELT_ENERGY_SILENCE;
|
||||
}
|
||||
memset(f->block[0].coeffs, 0, sizeof(f->block[0].coeffs));
|
||||
memset(f->block[1].coeffs, 0, sizeof(f->block[1].coeffs));
|
||||
}
|
||||
|
||||
/* transform and output for each output channel */
|
||||
for (i = 0; i < f->output_channels; i++) {
|
||||
CeltBlock *block = &f->block[i];
|
||||
|
||||
/* iMDCT and overlap-add */
|
||||
for (j = 0; j < f->blocks; j++) {
|
||||
float *dst = block->buf + 1024 + j * f->blocksize;
|
||||
|
||||
imdct_fn(imdct, dst + CELT_OVERLAP / 2, f->block[i].coeffs + j,
|
||||
sizeof(float)*f->blocks);
|
||||
f->dsp->vector_fmul_window(dst, dst, dst + CELT_OVERLAP / 2,
|
||||
ff_celt_window, CELT_OVERLAP / 2);
|
||||
}
|
||||
|
||||
if (downmix)
|
||||
f->dsp->vector_fmul_scalar(&block->buf[1024], &block->buf[1024], 0.5f, frame_size);
|
||||
|
||||
/* postfilter */
|
||||
celt_postfilter(f, block);
|
||||
|
||||
/* deemphasis */
|
||||
block->emph_coeff = f->opusdsp.deemphasis(output[i],
|
||||
&block->buf[1024 - frame_size],
|
||||
block->emph_coeff,
|
||||
ff_opus_deemph_weights,
|
||||
frame_size);
|
||||
}
|
||||
|
||||
if (channels == 1)
|
||||
memcpy(f->block[1].energy, f->block[0].energy, sizeof(f->block[0].energy));
|
||||
|
||||
for (i = 0; i < 2; i++ ) {
|
||||
CeltBlock *block = &f->block[i];
|
||||
|
||||
if (!f->transient) {
|
||||
memcpy(block->prev_energy[1], block->prev_energy[0], sizeof(block->prev_energy[0]));
|
||||
memcpy(block->prev_energy[0], block->energy, sizeof(block->prev_energy[0]));
|
||||
} else {
|
||||
for (j = 0; j < CELT_MAX_BANDS; j++)
|
||||
block->prev_energy[0][j] = FFMIN(block->prev_energy[0][j], block->energy[j]);
|
||||
}
|
||||
|
||||
for (j = 0; j < f->start_band; j++) {
|
||||
block->prev_energy[0][j] = CELT_ENERGY_SILENCE;
|
||||
block->energy[j] = 0.0;
|
||||
}
|
||||
for (j = f->end_band; j < CELT_MAX_BANDS; j++) {
|
||||
block->prev_energy[0][j] = CELT_ENERGY_SILENCE;
|
||||
block->energy[j] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
f->seed = rc->range;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_celt_flush(CeltFrame *f)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (f->flushed)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
CeltBlock *block = &f->block[i];
|
||||
|
||||
for (j = 0; j < CELT_MAX_BANDS; j++)
|
||||
block->prev_energy[0][j] = block->prev_energy[1][j] = CELT_ENERGY_SILENCE;
|
||||
|
||||
memset(block->energy, 0, sizeof(block->energy));
|
||||
memset(block->buf, 0, sizeof(block->buf));
|
||||
|
||||
memset(block->pf_gains, 0, sizeof(block->pf_gains));
|
||||
memset(block->pf_gains_old, 0, sizeof(block->pf_gains_old));
|
||||
memset(block->pf_gains_new, 0, sizeof(block->pf_gains_new));
|
||||
|
||||
/* libopus uses CELT_EMPH_COEFF on init, but 0 is better since there's
|
||||
* a lesser discontinuity when seeking.
|
||||
* The deemphasis functions differ from libopus in that they require
|
||||
* an initial state divided by the coefficient. */
|
||||
block->emph_coeff = 0.0f / ff_opus_deemph_weights[0];
|
||||
}
|
||||
f->seed = 0;
|
||||
|
||||
f->flushed = 1;
|
||||
}
|
||||
|
||||
void ff_celt_free(CeltFrame **f)
|
||||
{
|
||||
CeltFrame *frm = *f;
|
||||
int i;
|
||||
|
||||
if (!frm)
|
||||
return;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(frm->tx); i++)
|
||||
av_tx_uninit(&frm->tx[i]);
|
||||
|
||||
ff_celt_pvq_uninit(&frm->pvq);
|
||||
|
||||
av_freep(&frm->dsp);
|
||||
av_freep(f);
|
||||
}
|
||||
|
||||
int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels,
|
||||
int apply_phase_inv)
|
||||
{
|
||||
CeltFrame *frm;
|
||||
int i, ret;
|
||||
|
||||
if (output_channels != 1 && output_channels != 2) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid number of output channels: %d\n",
|
||||
output_channels);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
frm = av_mallocz(sizeof(*frm));
|
||||
if (!frm)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
frm->avctx = avctx;
|
||||
frm->output_channels = output_channels;
|
||||
frm->apply_phase_inv = apply_phase_inv;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(frm->tx); i++) {
|
||||
const float scale = -1.0f/32768;
|
||||
if ((ret = av_tx_init(&frm->tx[i], &frm->tx_fn[i], AV_TX_FLOAT_MDCT, 1, 15 << (i + 3), &scale, 0)) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((ret = ff_celt_pvq_init(&frm->pvq, 0)) < 0)
|
||||
goto fail;
|
||||
|
||||
frm->dsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
|
||||
if (!frm->dsp) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ff_opus_dsp_init(&frm->opusdsp);
|
||||
ff_celt_flush(frm);
|
||||
|
||||
*f = frm;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
ff_celt_free(&frm);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
#include "dsp.h"
|
||||
|
||||
static void postfilter_c(float *data, int period, float *gains, int len)
|
||||
{
|
||||
const float g0 = gains[0];
|
||||
const float g1 = gains[1];
|
||||
const float g2 = gains[2];
|
||||
|
||||
float x4 = data[-period - 2];
|
||||
float x3 = data[-period - 1];
|
||||
float x2 = data[-period + 0];
|
||||
float x1 = data[-period + 1];
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
float x0 = data[i - period + 2];
|
||||
data[i] += g0 * x2 +
|
||||
g1 * (x1 + x3) +
|
||||
g2 * (x0 + x4);
|
||||
x4 = x3;
|
||||
x3 = x2;
|
||||
x2 = x1;
|
||||
x1 = x0;
|
||||
}
|
||||
}
|
||||
|
||||
static float deemphasis_c(float *y, float *x, float coeff, const float *weights, int len)
|
||||
{
|
||||
const float c = weights[0];
|
||||
for (int i = 0; i < len; i++)
|
||||
coeff = y[i] = x[i] + coeff*c;
|
||||
|
||||
return coeff;
|
||||
}
|
||||
|
||||
av_cold void ff_opus_dsp_init(OpusDSP *ctx)
|
||||
{
|
||||
ctx->postfilter = postfilter_c;
|
||||
ctx->deemphasis = deemphasis_c;
|
||||
|
||||
#if ARCH_AARCH64
|
||||
ff_opus_dsp_init_aarch64(ctx);
|
||||
#elif ARCH_RISCV
|
||||
ff_opus_dsp_init_riscv(ctx);
|
||||
#elif ARCH_X86
|
||||
ff_opus_dsp_init_x86(ctx);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_DSP_H
|
||||
#define AVCODEC_OPUS_DSP_H
|
||||
|
||||
typedef struct OpusDSP {
|
||||
void (*postfilter)(float *data, int period, float *gains, int len);
|
||||
float (*deemphasis)(float *out, float *in, float coeff, const float *weights, int len);
|
||||
} OpusDSP;
|
||||
|
||||
void ff_opus_dsp_init(OpusDSP *ctx);
|
||||
|
||||
void ff_opus_dsp_init_x86(OpusDSP *ctx);
|
||||
void ff_opus_dsp_init_aarch64(OpusDSP *ctx);
|
||||
void ff_opus_dsp_init_riscv(OpusDSP *ctx);
|
||||
|
||||
#endif /* AVCODEC_OPUS_DSP_H */
|
||||
@@ -0,0 +1,752 @@
|
||||
/*
|
||||
* Opus encoder
|
||||
* Copyright (c) 2017 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include "encode.h"
|
||||
#include "enc.h"
|
||||
#include "pvq.h"
|
||||
#include "enc_psy.h"
|
||||
#include "tab.h"
|
||||
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/float_dsp.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "bytestream.h"
|
||||
#include "audio_frame_queue.h"
|
||||
#include "codec_internal.h"
|
||||
|
||||
typedef struct OpusEncContext {
|
||||
AVClass *av_class;
|
||||
OpusEncOptions options;
|
||||
OpusPsyContext psyctx;
|
||||
AVCodecContext *avctx;
|
||||
AudioFrameQueue afq;
|
||||
AVFloatDSPContext *dsp;
|
||||
AVTXContext *tx[CELT_BLOCK_NB];
|
||||
av_tx_fn tx_fn[CELT_BLOCK_NB];
|
||||
CeltPVQ *pvq;
|
||||
struct FFBufQueue bufqueue;
|
||||
|
||||
uint8_t enc_id[64];
|
||||
int enc_id_bits;
|
||||
|
||||
OpusPacketInfo packet;
|
||||
|
||||
int channels;
|
||||
|
||||
CeltFrame *frame;
|
||||
OpusRangeCoder *rc;
|
||||
|
||||
/* Actual energy the decoder will have */
|
||||
float last_quantized_energy[OPUS_MAX_CHANNELS][CELT_MAX_BANDS];
|
||||
|
||||
DECLARE_ALIGNED(32, float, scratch)[2048];
|
||||
} OpusEncContext;
|
||||
|
||||
static void opus_write_extradata(AVCodecContext *avctx)
|
||||
{
|
||||
uint8_t *bs = avctx->extradata;
|
||||
|
||||
bytestream_put_buffer(&bs, "OpusHead", 8);
|
||||
bytestream_put_byte (&bs, 0x1);
|
||||
bytestream_put_byte (&bs, avctx->ch_layout.nb_channels);
|
||||
bytestream_put_le16 (&bs, avctx->initial_padding);
|
||||
bytestream_put_le32 (&bs, avctx->sample_rate);
|
||||
bytestream_put_le16 (&bs, 0x0);
|
||||
bytestream_put_byte (&bs, 0x0); /* Default layout */
|
||||
}
|
||||
|
||||
static int opus_gen_toc(OpusEncContext *s, uint8_t *toc, int *size, int *fsize_needed)
|
||||
{
|
||||
int tmp = 0x0, extended_toc = 0;
|
||||
static const int toc_cfg[][OPUS_MODE_NB][OPUS_BANDWITH_NB] = {
|
||||
/* Silk Hybrid Celt Layer */
|
||||
/* NB MB WB SWB FB NB MB WB SWB FB NB MB WB SWB FB Bandwidth */
|
||||
{ { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 17, 0, 21, 25, 29 } }, /* 2.5 ms */
|
||||
{ { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, { 18, 0, 22, 26, 30 } }, /* 5 ms */
|
||||
{ { 1, 5, 9, 0, 0 }, { 0, 0, 0, 13, 15 }, { 19, 0, 23, 27, 31 } }, /* 10 ms */
|
||||
{ { 2, 6, 10, 0, 0 }, { 0, 0, 0, 14, 16 }, { 20, 0, 24, 28, 32 } }, /* 20 ms */
|
||||
{ { 3, 7, 11, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 } }, /* 40 ms */
|
||||
{ { 4, 8, 12, 0, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 } }, /* 60 ms */
|
||||
};
|
||||
int cfg = toc_cfg[s->packet.framesize][s->packet.mode][s->packet.bandwidth];
|
||||
*fsize_needed = 0;
|
||||
if (!cfg)
|
||||
return 1;
|
||||
if (s->packet.frames == 2) { /* 2 packets */
|
||||
if (s->frame[0].framebits == s->frame[1].framebits) { /* same size */
|
||||
tmp = 0x1;
|
||||
} else { /* different size */
|
||||
tmp = 0x2;
|
||||
*fsize_needed = 1; /* put frame sizes in the packet */
|
||||
}
|
||||
} else if (s->packet.frames > 2) {
|
||||
tmp = 0x3;
|
||||
extended_toc = 1;
|
||||
}
|
||||
tmp |= (s->channels > 1) << 2; /* Stereo or mono */
|
||||
tmp |= (cfg - 1) << 3; /* codec configuration */
|
||||
*toc++ = tmp;
|
||||
if (extended_toc) {
|
||||
for (int i = 0; i < (s->packet.frames - 1); i++)
|
||||
*fsize_needed |= (s->frame[i].framebits != s->frame[i + 1].framebits);
|
||||
tmp = (*fsize_needed) << 7; /* vbr flag */
|
||||
tmp |= (0) << 6; /* padding flag */
|
||||
tmp |= s->packet.frames;
|
||||
*toc++ = tmp;
|
||||
}
|
||||
*size = 1 + extended_toc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void celt_frame_setup_input(OpusEncContext *s, CeltFrame *f)
|
||||
{
|
||||
AVFrame *cur = NULL;
|
||||
const int subframesize = s->avctx->frame_size;
|
||||
int subframes = OPUS_BLOCK_SIZE(s->packet.framesize) / subframesize;
|
||||
|
||||
cur = ff_bufqueue_get(&s->bufqueue);
|
||||
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *b = &f->block[ch];
|
||||
const void *input = cur->extended_data[ch];
|
||||
size_t bps = av_get_bytes_per_sample(cur->format);
|
||||
memcpy(b->overlap, input, bps*cur->nb_samples);
|
||||
}
|
||||
|
||||
av_frame_free(&cur);
|
||||
|
||||
for (int sf = 0; sf < subframes; sf++) {
|
||||
if (sf != (subframes - 1))
|
||||
cur = ff_bufqueue_get(&s->bufqueue);
|
||||
else
|
||||
cur = ff_bufqueue_peek(&s->bufqueue, 0);
|
||||
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *b = &f->block[ch];
|
||||
const void *input = cur->extended_data[ch];
|
||||
const size_t bps = av_get_bytes_per_sample(cur->format);
|
||||
const size_t left = (subframesize - cur->nb_samples)*bps;
|
||||
const size_t len = FFMIN(subframesize, cur->nb_samples)*bps;
|
||||
memcpy(&b->samples[sf*subframesize], input, len);
|
||||
memset(&b->samples[cur->nb_samples], 0, left);
|
||||
}
|
||||
|
||||
/* Last frame isn't popped off and freed yet - we need it for overlap */
|
||||
if (sf != (subframes - 1))
|
||||
av_frame_free(&cur);
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply the pre emphasis filter */
|
||||
static void celt_apply_preemph_filter(OpusEncContext *s, CeltFrame *f)
|
||||
{
|
||||
const int subframesize = s->avctx->frame_size;
|
||||
const int subframes = OPUS_BLOCK_SIZE(s->packet.framesize) / subframesize;
|
||||
const float c = ff_opus_deemph_weights[0];
|
||||
|
||||
/* Filter overlap */
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *b = &f->block[ch];
|
||||
float m = b->emph_coeff;
|
||||
for (int i = 0; i < CELT_OVERLAP; i++) {
|
||||
float sample = b->overlap[i];
|
||||
b->overlap[i] = sample - m;
|
||||
m = sample * c;
|
||||
}
|
||||
b->emph_coeff = m;
|
||||
}
|
||||
|
||||
/* Filter the samples but do not update the last subframe's coeff - overlap ^^^ */
|
||||
for (int sf = 0; sf < subframes; sf++) {
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *b = &f->block[ch];
|
||||
float m = b->emph_coeff;
|
||||
for (int i = 0; i < subframesize; i++) {
|
||||
float sample = b->samples[sf*subframesize + i];
|
||||
b->samples[sf*subframesize + i] = sample - m;
|
||||
m = sample * c;
|
||||
}
|
||||
if (sf != (subframes - 1))
|
||||
b->emph_coeff = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the window and do the mdct */
|
||||
static void celt_frame_mdct(OpusEncContext *s, CeltFrame *f)
|
||||
{
|
||||
float *win = s->scratch, *temp = s->scratch + 1920;
|
||||
|
||||
if (f->transient) {
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *b = &f->block[ch];
|
||||
float *src1 = b->overlap;
|
||||
for (int t = 0; t < f->blocks; t++) {
|
||||
float *src2 = &b->samples[CELT_OVERLAP*t];
|
||||
s->dsp->vector_fmul(win, src1, ff_celt_window, 128);
|
||||
s->dsp->vector_fmul_reverse(&win[CELT_OVERLAP], src2,
|
||||
ff_celt_window_padded, 128);
|
||||
src1 = src2;
|
||||
s->tx_fn[0](s->tx[0], b->coeffs + t, win, sizeof(float)*f->blocks);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int blk_len = OPUS_BLOCK_SIZE(f->size), wlen = OPUS_BLOCK_SIZE(f->size + 1);
|
||||
int rwin = blk_len - CELT_OVERLAP, lap_dst = (wlen - blk_len - CELT_OVERLAP) >> 1;
|
||||
memset(win, 0, wlen*sizeof(float));
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *b = &f->block[ch];
|
||||
|
||||
/* Overlap */
|
||||
s->dsp->vector_fmul(temp, b->overlap, ff_celt_window, 128);
|
||||
memcpy(win + lap_dst, temp, CELT_OVERLAP*sizeof(float));
|
||||
|
||||
/* Samples, flat top window */
|
||||
memcpy(&win[lap_dst + CELT_OVERLAP], b->samples, rwin*sizeof(float));
|
||||
|
||||
/* Samples, windowed */
|
||||
s->dsp->vector_fmul_reverse(temp, b->samples + rwin,
|
||||
ff_celt_window_padded, 128);
|
||||
memcpy(win + lap_dst + blk_len, temp, CELT_OVERLAP*sizeof(float));
|
||||
|
||||
s->tx_fn[f->size](s->tx[f->size], b->coeffs, win, sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *block = &f->block[ch];
|
||||
for (int i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
float ener = 0.0f;
|
||||
int band_offset = ff_celt_freq_bands[i] << f->size;
|
||||
int band_size = ff_celt_freq_range[i] << f->size;
|
||||
float *coeffs = &block->coeffs[band_offset];
|
||||
|
||||
for (int j = 0; j < band_size; j++)
|
||||
ener += coeffs[j]*coeffs[j];
|
||||
|
||||
block->lin_energy[i] = sqrtf(ener) + FLT_EPSILON;
|
||||
ener = 1.0f/block->lin_energy[i];
|
||||
|
||||
for (int j = 0; j < band_size; j++)
|
||||
coeffs[j] *= ener;
|
||||
|
||||
block->energy[i] = log2f(block->lin_energy[i]) - ff_celt_mean_energy[i];
|
||||
|
||||
/* CELT_ENERGY_SILENCE is what the decoder uses and its not -infinity */
|
||||
block->energy[i] = FFMAX(block->energy[i], CELT_ENERGY_SILENCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_enc_tf(CeltFrame *f, OpusRangeCoder *rc)
|
||||
{
|
||||
int tf_select = 0, diff = 0, tf_changed = 0, tf_select_needed;
|
||||
int bits = f->transient ? 2 : 4;
|
||||
|
||||
tf_select_needed = ((f->size && (opus_rc_tell(rc) + bits + 1) <= f->framebits));
|
||||
|
||||
for (int i = f->start_band; i < f->end_band; i++) {
|
||||
if ((opus_rc_tell(rc) + bits + tf_select_needed) <= f->framebits) {
|
||||
const int tbit = (diff ^ 1) == f->tf_change[i];
|
||||
ff_opus_rc_enc_log(rc, tbit, bits);
|
||||
diff ^= tbit;
|
||||
tf_changed |= diff;
|
||||
}
|
||||
bits = f->transient ? 4 : 5;
|
||||
}
|
||||
|
||||
if (tf_select_needed && ff_celt_tf_select[f->size][f->transient][0][tf_changed] !=
|
||||
ff_celt_tf_select[f->size][f->transient][1][tf_changed]) {
|
||||
ff_opus_rc_enc_log(rc, f->tf_select, 1);
|
||||
tf_select = f->tf_select;
|
||||
}
|
||||
|
||||
for (int i = f->start_band; i < f->end_band; i++)
|
||||
f->tf_change[i] = ff_celt_tf_select[f->size][f->transient][tf_select][f->tf_change[i]];
|
||||
}
|
||||
|
||||
static void celt_enc_quant_pfilter(OpusRangeCoder *rc, CeltFrame *f)
|
||||
{
|
||||
float gain = f->pf_gain;
|
||||
int txval, octave = f->pf_octave, period = f->pf_period, tapset = f->pf_tapset;
|
||||
|
||||
ff_opus_rc_enc_log(rc, f->pfilter, 1);
|
||||
if (!f->pfilter)
|
||||
return;
|
||||
|
||||
/* Octave */
|
||||
txval = FFMIN(octave, 6);
|
||||
ff_opus_rc_enc_uint(rc, txval, 6);
|
||||
octave = txval;
|
||||
/* Period */
|
||||
txval = av_clip(period - (16 << octave) + 1, 0, (1 << (4 + octave)) - 1);
|
||||
ff_opus_rc_put_raw(rc, period, 4 + octave);
|
||||
period = txval + (16 << octave) - 1;
|
||||
/* Gain */
|
||||
txval = FFMIN(((int)(gain / 0.09375f)) - 1, 7);
|
||||
ff_opus_rc_put_raw(rc, txval, 3);
|
||||
gain = 0.09375f * (txval + 1);
|
||||
/* Tapset */
|
||||
if ((opus_rc_tell(rc) + 2) <= f->framebits)
|
||||
ff_opus_rc_enc_cdf(rc, tapset, ff_celt_model_tapset);
|
||||
else
|
||||
tapset = 0;
|
||||
/* Finally create the coeffs */
|
||||
for (int i = 0; i < 2; i++) {
|
||||
CeltBlock *block = &f->block[i];
|
||||
|
||||
block->pf_period_new = FFMAX(period, CELT_POSTFILTER_MINPERIOD);
|
||||
block->pf_gains_new[0] = gain * ff_celt_postfilter_taps[tapset][0];
|
||||
block->pf_gains_new[1] = gain * ff_celt_postfilter_taps[tapset][1];
|
||||
block->pf_gains_new[2] = gain * ff_celt_postfilter_taps[tapset][2];
|
||||
}
|
||||
}
|
||||
|
||||
static void exp_quant_coarse(OpusRangeCoder *rc, CeltFrame *f,
|
||||
float last_energy[][CELT_MAX_BANDS], int intra)
|
||||
{
|
||||
float alpha, beta, prev[2] = { 0, 0 };
|
||||
const uint8_t *pmod = ff_celt_coarse_energy_dist[f->size][intra];
|
||||
|
||||
/* Inter is really just differential coding */
|
||||
if (opus_rc_tell(rc) + 3 <= f->framebits)
|
||||
ff_opus_rc_enc_log(rc, intra, 3);
|
||||
else
|
||||
intra = 0;
|
||||
|
||||
if (intra) {
|
||||
alpha = 0.0f;
|
||||
beta = 1.0f - (4915.0f/32768.0f);
|
||||
} else {
|
||||
alpha = ff_celt_alpha_coef[f->size];
|
||||
beta = ff_celt_beta_coef[f->size];
|
||||
}
|
||||
|
||||
for (int i = f->start_band; i < f->end_band; i++) {
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *block = &f->block[ch];
|
||||
const int left = f->framebits - opus_rc_tell(rc);
|
||||
const float last = FFMAX(-9.0f, last_energy[ch][i]);
|
||||
float diff = block->energy[i] - prev[ch] - last*alpha;
|
||||
int q_en = lrintf(diff);
|
||||
if (left >= 15) {
|
||||
ff_opus_rc_enc_laplace(rc, &q_en, pmod[i << 1] << 7, pmod[(i << 1) + 1] << 6);
|
||||
} else if (left >= 2) {
|
||||
q_en = av_clip(q_en, -1, 1);
|
||||
ff_opus_rc_enc_cdf(rc, 2*q_en + 3*(q_en < 0), ff_celt_model_energy_small);
|
||||
} else if (left >= 1) {
|
||||
q_en = av_clip(q_en, -1, 0);
|
||||
ff_opus_rc_enc_log(rc, (q_en & 1), 1);
|
||||
} else q_en = -1;
|
||||
|
||||
block->error_energy[i] = q_en - diff;
|
||||
prev[ch] += beta * q_en;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_quant_coarse(CeltFrame *f, OpusRangeCoder *rc,
|
||||
float last_energy[][CELT_MAX_BANDS])
|
||||
{
|
||||
uint32_t inter, intra;
|
||||
OPUS_RC_CHECKPOINT_SPAWN(rc);
|
||||
|
||||
exp_quant_coarse(rc, f, last_energy, 1);
|
||||
intra = OPUS_RC_CHECKPOINT_BITS(rc);
|
||||
|
||||
OPUS_RC_CHECKPOINT_ROLLBACK(rc);
|
||||
|
||||
exp_quant_coarse(rc, f, last_energy, 0);
|
||||
inter = OPUS_RC_CHECKPOINT_BITS(rc);
|
||||
|
||||
if (inter > intra) { /* Unlikely */
|
||||
OPUS_RC_CHECKPOINT_ROLLBACK(rc);
|
||||
exp_quant_coarse(rc, f, last_energy, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_quant_fine(CeltFrame *f, OpusRangeCoder *rc)
|
||||
{
|
||||
for (int i = f->start_band; i < f->end_band; i++) {
|
||||
if (!f->fine_bits[i])
|
||||
continue;
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *block = &f->block[ch];
|
||||
int quant, lim = (1 << f->fine_bits[i]);
|
||||
float offset, diff = 0.5f - block->error_energy[i];
|
||||
quant = av_clip(floor(diff*lim), 0, lim - 1);
|
||||
ff_opus_rc_put_raw(rc, quant, f->fine_bits[i]);
|
||||
offset = 0.5f - ((quant + 0.5f) * (1 << (14 - f->fine_bits[i])) / 16384.0f);
|
||||
block->error_energy[i] -= offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_quant_final(OpusEncContext *s, OpusRangeCoder *rc, CeltFrame *f)
|
||||
{
|
||||
for (int priority = 0; priority < 2; priority++) {
|
||||
for (int i = f->start_band; i < f->end_band && (f->framebits - opus_rc_tell(rc)) >= f->channels; i++) {
|
||||
if (f->fine_priority[i] != priority || f->fine_bits[i] >= CELT_MAX_FINE_BITS)
|
||||
continue;
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *block = &f->block[ch];
|
||||
const float err = block->error_energy[i];
|
||||
const float offset = 0.5f * (1 << (14 - f->fine_bits[i] - 1)) / 16384.0f;
|
||||
const int sign = FFABS(err + offset) < FFABS(err - offset);
|
||||
ff_opus_rc_put_raw(rc, sign, 1);
|
||||
block->error_energy[i] -= offset*(1 - 2*sign);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_encode_frame(OpusEncContext *s, OpusRangeCoder *rc,
|
||||
CeltFrame *f, int index)
|
||||
{
|
||||
ff_opus_rc_enc_init(rc);
|
||||
|
||||
ff_opus_psy_celt_frame_init(&s->psyctx, f, index);
|
||||
|
||||
celt_frame_setup_input(s, f);
|
||||
|
||||
if (f->silence) {
|
||||
if (f->framebits >= 16)
|
||||
ff_opus_rc_enc_log(rc, 1, 15); /* Silence (if using explicit signalling) */
|
||||
for (int ch = 0; ch < s->channels; ch++)
|
||||
memset(s->last_quantized_energy[ch], 0.0f, sizeof(float)*CELT_MAX_BANDS);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Filters */
|
||||
celt_apply_preemph_filter(s, f);
|
||||
if (f->pfilter) {
|
||||
ff_opus_rc_enc_log(rc, 0, 15);
|
||||
celt_enc_quant_pfilter(rc, f);
|
||||
}
|
||||
|
||||
/* Transform */
|
||||
celt_frame_mdct(s, f);
|
||||
|
||||
/* Need to handle transient/non-transient switches at any point during analysis */
|
||||
while (ff_opus_psy_celt_frame_process(&s->psyctx, f, index))
|
||||
celt_frame_mdct(s, f);
|
||||
|
||||
ff_opus_rc_enc_init(rc);
|
||||
|
||||
/* Silence */
|
||||
ff_opus_rc_enc_log(rc, 0, 15);
|
||||
|
||||
/* Pitch filter */
|
||||
if (!f->start_band && opus_rc_tell(rc) + 16 <= f->framebits)
|
||||
celt_enc_quant_pfilter(rc, f);
|
||||
|
||||
/* Transient flag */
|
||||
if (f->size && opus_rc_tell(rc) + 3 <= f->framebits)
|
||||
ff_opus_rc_enc_log(rc, f->transient, 3);
|
||||
|
||||
/* Main encoding */
|
||||
celt_quant_coarse (f, rc, s->last_quantized_energy);
|
||||
celt_enc_tf (f, rc);
|
||||
ff_celt_bitalloc (f, rc, 1);
|
||||
celt_quant_fine (f, rc);
|
||||
ff_celt_quant_bands(f, rc);
|
||||
|
||||
/* Anticollapse bit */
|
||||
if (f->anticollapse_needed)
|
||||
ff_opus_rc_put_raw(rc, f->anticollapse, 1);
|
||||
|
||||
/* Final per-band energy adjustments from leftover bits */
|
||||
celt_quant_final(s, rc, f);
|
||||
|
||||
for (int ch = 0; ch < f->channels; ch++) {
|
||||
CeltBlock *block = &f->block[ch];
|
||||
for (int i = 0; i < CELT_MAX_BANDS; i++)
|
||||
s->last_quantized_energy[ch][i] = block->energy[i] + block->error_energy[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline int write_opuslacing(uint8_t *dst, int v)
|
||||
{
|
||||
dst[0] = FFMIN(v - FFALIGN(v - 255, 4), v);
|
||||
dst[1] = v - dst[0] >> 2;
|
||||
return 1 + (v >= 252);
|
||||
}
|
||||
|
||||
static void opus_packet_assembler(OpusEncContext *s, AVPacket *avpkt)
|
||||
{
|
||||
int offset, fsize_needed;
|
||||
|
||||
/* Write toc */
|
||||
opus_gen_toc(s, avpkt->data, &offset, &fsize_needed);
|
||||
|
||||
/* Frame sizes if needed */
|
||||
if (fsize_needed) {
|
||||
for (int i = 0; i < s->packet.frames - 1; i++) {
|
||||
offset += write_opuslacing(avpkt->data + offset,
|
||||
s->frame[i].framebits >> 3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Packets */
|
||||
for (int i = 0; i < s->packet.frames; i++) {
|
||||
ff_opus_rc_enc_end(&s->rc[i], avpkt->data + offset,
|
||||
s->frame[i].framebits >> 3);
|
||||
offset += s->frame[i].framebits >> 3;
|
||||
}
|
||||
|
||||
avpkt->size = offset;
|
||||
}
|
||||
|
||||
/* Used as overlap for the first frame and padding for the last encoded packet */
|
||||
static AVFrame *spawn_empty_frame(OpusEncContext *s)
|
||||
{
|
||||
AVFrame *f = av_frame_alloc();
|
||||
int ret;
|
||||
if (!f)
|
||||
return NULL;
|
||||
f->format = s->avctx->sample_fmt;
|
||||
f->nb_samples = s->avctx->frame_size;
|
||||
ret = av_channel_layout_copy(&f->ch_layout, &s->avctx->ch_layout);
|
||||
if (ret < 0) {
|
||||
av_frame_free(&f);
|
||||
return NULL;
|
||||
}
|
||||
if (av_frame_get_buffer(f, 4)) {
|
||||
av_frame_free(&f);
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < s->channels; i++) {
|
||||
size_t bps = av_get_bytes_per_sample(f->format);
|
||||
memset(f->extended_data[i], 0, bps*f->nb_samples);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
static int opus_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
|
||||
const AVFrame *frame, int *got_packet_ptr)
|
||||
{
|
||||
OpusEncContext *s = avctx->priv_data;
|
||||
int ret, frame_size, alloc_size = 0;
|
||||
|
||||
if (frame) { /* Add new frame to queue */
|
||||
if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
|
||||
return ret;
|
||||
ff_bufqueue_add(avctx, &s->bufqueue, av_frame_clone(frame));
|
||||
} else {
|
||||
ff_opus_psy_signal_eof(&s->psyctx);
|
||||
if (!s->afq.remaining_samples || !avctx->frame_num)
|
||||
return 0; /* We've been flushed and there's nothing left to encode */
|
||||
}
|
||||
|
||||
/* Run the psychoacoustic system */
|
||||
if (ff_opus_psy_process(&s->psyctx, &s->packet))
|
||||
return 0;
|
||||
|
||||
frame_size = OPUS_BLOCK_SIZE(s->packet.framesize);
|
||||
|
||||
if (!frame) {
|
||||
/* This can go negative, that's not a problem, we only pad if positive */
|
||||
int pad_empty = s->packet.frames*(frame_size/s->avctx->frame_size) - s->bufqueue.available + 1;
|
||||
/* Pad with empty 2.5 ms frames to whatever framesize was decided,
|
||||
* this should only happen at the very last flush frame. The frames
|
||||
* allocated here will be freed (because they have no other references)
|
||||
* after they get used by celt_frame_setup_input() */
|
||||
for (int i = 0; i < pad_empty; i++) {
|
||||
AVFrame *empty = spawn_empty_frame(s);
|
||||
if (!empty)
|
||||
return AVERROR(ENOMEM);
|
||||
ff_bufqueue_add(avctx, &s->bufqueue, empty);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < s->packet.frames; i++) {
|
||||
celt_encode_frame(s, &s->rc[i], &s->frame[i], i);
|
||||
alloc_size += s->frame[i].framebits >> 3;
|
||||
}
|
||||
|
||||
/* Worst case toc + the frame lengths if needed */
|
||||
alloc_size += 2 + s->packet.frames*2;
|
||||
|
||||
if ((ret = ff_alloc_packet(avctx, avpkt, alloc_size)) < 0)
|
||||
return ret;
|
||||
|
||||
/* Assemble packet */
|
||||
opus_packet_assembler(s, avpkt);
|
||||
|
||||
/* Update the psychoacoustic system */
|
||||
ff_opus_psy_postencode_update(&s->psyctx, s->frame);
|
||||
|
||||
/* Remove samples from queue and skip if needed */
|
||||
ff_af_queue_remove(&s->afq, s->packet.frames*frame_size, &avpkt->pts, &avpkt->duration);
|
||||
if (s->packet.frames*frame_size > avpkt->duration) {
|
||||
uint8_t *side = av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
|
||||
if (!side)
|
||||
return AVERROR(ENOMEM);
|
||||
AV_WL32(&side[4], s->packet.frames*frame_size - avpkt->duration + 120);
|
||||
}
|
||||
|
||||
*got_packet_ptr = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_cold int opus_encode_end(AVCodecContext *avctx)
|
||||
{
|
||||
OpusEncContext *s = avctx->priv_data;
|
||||
|
||||
for (int i = 0; i < CELT_BLOCK_NB; i++)
|
||||
av_tx_uninit(&s->tx[i]);
|
||||
|
||||
ff_celt_pvq_uninit(&s->pvq);
|
||||
av_freep(&s->dsp);
|
||||
av_freep(&s->frame);
|
||||
av_freep(&s->rc);
|
||||
ff_af_queue_close(&s->afq);
|
||||
ff_opus_psy_end(&s->psyctx);
|
||||
ff_bufqueue_discard_all(&s->bufqueue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_cold int opus_encode_init(AVCodecContext *avctx)
|
||||
{
|
||||
int ret, max_frames;
|
||||
OpusEncContext *s = avctx->priv_data;
|
||||
|
||||
s->avctx = avctx;
|
||||
s->channels = avctx->ch_layout.nb_channels;
|
||||
|
||||
/* Opus allows us to change the framesize on each packet (and each packet may
|
||||
* have multiple frames in it) but we can't change the codec's frame size on
|
||||
* runtime, so fix it to the lowest possible number of samples and use a queue
|
||||
* to accumulate AVFrames until we have enough to encode whatever the encoder
|
||||
* decides is the best */
|
||||
avctx->frame_size = 120;
|
||||
/* Initial padding will change if SILK is ever supported */
|
||||
avctx->initial_padding = 120;
|
||||
|
||||
if (!avctx->bit_rate) {
|
||||
int coupled = ff_opus_default_coupled_streams[s->channels - 1];
|
||||
avctx->bit_rate = coupled*(96000) + (s->channels - coupled*2)*(48000);
|
||||
} else if (avctx->bit_rate < 6000 || avctx->bit_rate > 255000 * s->channels) {
|
||||
int64_t clipped_rate = av_clip(avctx->bit_rate, 6000, 255000 * s->channels);
|
||||
av_log(avctx, AV_LOG_ERROR, "Unsupported bitrate %"PRId64" kbps, clipping to %"PRId64" kbps\n",
|
||||
avctx->bit_rate/1000, clipped_rate/1000);
|
||||
avctx->bit_rate = clipped_rate;
|
||||
}
|
||||
|
||||
/* Extradata */
|
||||
avctx->extradata_size = 19;
|
||||
avctx->extradata = av_malloc(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!avctx->extradata)
|
||||
return AVERROR(ENOMEM);
|
||||
opus_write_extradata(avctx);
|
||||
|
||||
ff_af_queue_init(avctx, &s->afq);
|
||||
|
||||
if ((ret = ff_celt_pvq_init(&s->pvq, 1)) < 0)
|
||||
return ret;
|
||||
|
||||
if (!(s->dsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT)))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
/* I have no idea why a base scaling factor of 68 works, could be the twiddles */
|
||||
for (int i = 0; i < CELT_BLOCK_NB; i++) {
|
||||
const float scale = 68 << (CELT_BLOCK_NB - 1 - i);
|
||||
if ((ret = av_tx_init(&s->tx[i], &s->tx_fn[i], AV_TX_FLOAT_MDCT, 0, 15 << (i + 3), &scale, 0)))
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
/* Zero out previous energy (matters for inter first frame) */
|
||||
for (int ch = 0; ch < s->channels; ch++)
|
||||
memset(s->last_quantized_energy[ch], 0.0f, sizeof(float)*CELT_MAX_BANDS);
|
||||
|
||||
/* Allocate an empty frame to use as overlap for the first frame of audio */
|
||||
ff_bufqueue_add(avctx, &s->bufqueue, spawn_empty_frame(s));
|
||||
if (!ff_bufqueue_peek(&s->bufqueue, 0))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
if ((ret = ff_opus_psy_init(&s->psyctx, s->avctx, &s->bufqueue, &s->options)))
|
||||
return ret;
|
||||
|
||||
/* Frame structs and range coder buffers */
|
||||
max_frames = ceilf(FFMIN(s->options.max_delay_ms, 120.0f)/2.5f);
|
||||
s->frame = av_malloc(max_frames*sizeof(CeltFrame));
|
||||
if (!s->frame)
|
||||
return AVERROR(ENOMEM);
|
||||
s->rc = av_malloc(max_frames*sizeof(OpusRangeCoder));
|
||||
if (!s->rc)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
for (int i = 0; i < max_frames; i++) {
|
||||
s->frame[i].dsp = s->dsp;
|
||||
s->frame[i].avctx = s->avctx;
|
||||
s->frame[i].seed = 0;
|
||||
s->frame[i].pvq = s->pvq;
|
||||
s->frame[i].apply_phase_inv = s->options.apply_phase_inv;
|
||||
s->frame[i].block[0].emph_coeff = s->frame[i].block[1].emph_coeff = 0.0f;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define OPUSENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
|
||||
static const AVOption opusenc_options[] = {
|
||||
{ "opus_delay", "Maximum delay in milliseconds", offsetof(OpusEncContext, options.max_delay_ms), AV_OPT_TYPE_FLOAT, { .dbl = OPUS_MAX_LOOKAHEAD }, 2.5f, OPUS_MAX_LOOKAHEAD, OPUSENC_FLAGS, .unit = "max_delay_ms" },
|
||||
{ "apply_phase_inv", "Apply intensity stereo phase inversion", offsetof(OpusEncContext, options.apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, OPUSENC_FLAGS, .unit = "apply_phase_inv" },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const AVClass opusenc_class = {
|
||||
.class_name = "Opus encoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = opusenc_options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
static const FFCodecDefault opusenc_defaults[] = {
|
||||
{ "b", "0" },
|
||||
{ "compression_level", "10" },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
const FFCodec ff_opus_encoder = {
|
||||
.p.name = "opus",
|
||||
CODEC_LONG_NAME("Opus"),
|
||||
.p.type = AVMEDIA_TYPE_AUDIO,
|
||||
.p.id = AV_CODEC_ID_OPUS,
|
||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
|
||||
AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_EXPERIMENTAL,
|
||||
.defaults = opusenc_defaults,
|
||||
.p.priv_class = &opusenc_class,
|
||||
.priv_data_size = sizeof(OpusEncContext),
|
||||
.init = opus_encode_init,
|
||||
FF_CODEC_ENCODE_CB(opus_encode_frame),
|
||||
.close = opus_encode_end,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
CODEC_SAMPLERATES(48000),
|
||||
CODEC_CH_LAYOUTS(AV_CHANNEL_LAYOUT_MONO, AV_CHANNEL_LAYOUT_STEREO),
|
||||
CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP),
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Opus encoder
|
||||
* Copyright (c) 2017 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_ENC_H
|
||||
#define AVCODEC_OPUS_ENC_H
|
||||
|
||||
#include "libavutil/intmath.h"
|
||||
#include "opus.h"
|
||||
|
||||
/* Determines the maximum delay the psychoacoustic system will use for lookahead */
|
||||
#define FF_BUFQUEUE_SIZE 145
|
||||
#include "libavfilter/bufferqueue.h"
|
||||
|
||||
#define OPUS_MAX_LOOKAHEAD ((FF_BUFQUEUE_SIZE - 1)*2.5f)
|
||||
|
||||
#define OPUS_MAX_CHANNELS 2
|
||||
|
||||
/* 120 ms / 2.5 ms = 48 frames (extremely improbable, but the encoder'll work) */
|
||||
#define OPUS_MAX_FRAMES_PER_PACKET 48
|
||||
|
||||
#define OPUS_BLOCK_SIZE(x) (2 * 15 * (1 << ((x) + 2)))
|
||||
|
||||
#define OPUS_SAMPLES_TO_BLOCK_SIZE(x) (ff_log2((x) / (2 * 15)) - 2)
|
||||
|
||||
typedef struct OpusEncOptions {
|
||||
float max_delay_ms;
|
||||
int apply_phase_inv;
|
||||
} OpusEncOptions;
|
||||
|
||||
typedef struct OpusPacketInfo {
|
||||
enum OpusMode mode;
|
||||
enum OpusBandwidth bandwidth;
|
||||
int framesize;
|
||||
int frames;
|
||||
} OpusPacketInfo;
|
||||
|
||||
#endif /* AVCODEC_OPUS_ENC_H */
|
||||
@@ -0,0 +1,614 @@
|
||||
/*
|
||||
* Opus encoder
|
||||
* Copyright (c) 2017 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include "libavutil/mem.h"
|
||||
#include "enc_psy.h"
|
||||
#include "celt.h"
|
||||
#include "pvq.h"
|
||||
#include "tab.h"
|
||||
#include "libavfilter/window_func.h"
|
||||
|
||||
static float pvq_band_cost(CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int band,
|
||||
float *bits, float lambda)
|
||||
{
|
||||
int i, b = 0;
|
||||
uint32_t cm[2] = { (1 << f->blocks) - 1, (1 << f->blocks) - 1 };
|
||||
const int band_size = ff_celt_freq_range[band] << f->size;
|
||||
float buf[176 * 2], lowband_scratch[176], norm1[176], norm2[176];
|
||||
float dist, cost, err_x = 0.0f, err_y = 0.0f;
|
||||
float *X = buf;
|
||||
float *X_orig = f->block[0].coeffs + (ff_celt_freq_bands[band] << f->size);
|
||||
float *Y = (f->channels == 2) ? &buf[176] : NULL;
|
||||
float *Y_orig = f->block[1].coeffs + (ff_celt_freq_bands[band] << f->size);
|
||||
OPUS_RC_CHECKPOINT_SPAWN(rc);
|
||||
|
||||
memcpy(X, X_orig, band_size*sizeof(float));
|
||||
if (Y)
|
||||
memcpy(Y, Y_orig, band_size*sizeof(float));
|
||||
|
||||
f->remaining2 = ((f->framebits << 3) - f->anticollapse_needed) - opus_rc_tell_frac(rc) - 1;
|
||||
if (band <= f->coded_bands - 1) {
|
||||
int curr_balance = f->remaining / FFMIN(3, f->coded_bands - band);
|
||||
b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[band] + curr_balance), 14);
|
||||
}
|
||||
|
||||
if (f->dual_stereo) {
|
||||
pvq->quant_band(pvq, f, rc, band, X, NULL, band_size, b / 2, f->blocks, NULL,
|
||||
f->size, norm1, 0, 1.0f, lowband_scratch, cm[0]);
|
||||
|
||||
pvq->quant_band(pvq, f, rc, band, Y, NULL, band_size, b / 2, f->blocks, NULL,
|
||||
f->size, norm2, 0, 1.0f, lowband_scratch, cm[1]);
|
||||
} else {
|
||||
pvq->quant_band(pvq, f, rc, band, X, Y, band_size, b, f->blocks, NULL, f->size,
|
||||
norm1, 0, 1.0f, lowband_scratch, cm[0] | cm[1]);
|
||||
}
|
||||
|
||||
for (i = 0; i < band_size; i++) {
|
||||
err_x += (X[i] - X_orig[i])*(X[i] - X_orig[i]);
|
||||
if (Y)
|
||||
err_y += (Y[i] - Y_orig[i])*(Y[i] - Y_orig[i]);
|
||||
}
|
||||
|
||||
dist = sqrtf(err_x) + sqrtf(err_y);
|
||||
cost = OPUS_RC_CHECKPOINT_BITS(rc)/8.0f;
|
||||
*bits += cost;
|
||||
|
||||
OPUS_RC_CHECKPOINT_ROLLBACK(rc);
|
||||
|
||||
return lambda*dist*cost;
|
||||
}
|
||||
|
||||
/* Populate metrics without taking into consideration neighbouring steps */
|
||||
static void step_collect_psy_metrics(OpusPsyContext *s, int index)
|
||||
{
|
||||
int silence = 0, ch, i, j;
|
||||
OpusPsyStep *st = s->steps[index];
|
||||
|
||||
st->index = index;
|
||||
|
||||
for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) {
|
||||
const int lap_size = (1 << s->bsize_analysis);
|
||||
for (i = 1; i <= FFMIN(lap_size, index); i++) {
|
||||
const int offset = i*120;
|
||||
AVFrame *cur = ff_bufqueue_peek(s->bufqueue, index - i);
|
||||
memcpy(&s->scratch[offset], cur->extended_data[ch], cur->nb_samples*sizeof(float));
|
||||
}
|
||||
for (i = 0; i < lap_size; i++) {
|
||||
const int offset = i*120 + lap_size;
|
||||
AVFrame *cur = ff_bufqueue_peek(s->bufqueue, index + i);
|
||||
memcpy(&s->scratch[offset], cur->extended_data[ch], cur->nb_samples*sizeof(float));
|
||||
}
|
||||
|
||||
s->dsp->vector_fmul(s->scratch, s->scratch, s->window[s->bsize_analysis],
|
||||
(OPUS_BLOCK_SIZE(s->bsize_analysis) << 1));
|
||||
|
||||
s->mdct_fn[s->bsize_analysis](s->mdct[s->bsize_analysis], st->coeffs[ch],
|
||||
s->scratch, sizeof(float));
|
||||
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++)
|
||||
st->bands[ch][i] = &st->coeffs[ch][ff_celt_freq_bands[i] << s->bsize_analysis];
|
||||
}
|
||||
|
||||
for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) {
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
float avg_c_s, energy = 0.0f, dist_dev = 0.0f;
|
||||
const int range = ff_celt_freq_range[i] << s->bsize_analysis;
|
||||
const float *coeffs = st->bands[ch][i];
|
||||
for (j = 0; j < range; j++)
|
||||
energy += coeffs[j]*coeffs[j];
|
||||
|
||||
st->energy[ch][i] += sqrtf(energy);
|
||||
silence |= !!st->energy[ch][i];
|
||||
avg_c_s = energy / range;
|
||||
|
||||
for (j = 0; j < range; j++) {
|
||||
const float c_s = coeffs[j]*coeffs[j];
|
||||
dist_dev += (avg_c_s - c_s)*(avg_c_s - c_s);
|
||||
}
|
||||
|
||||
st->tone[ch][i] += sqrtf(dist_dev);
|
||||
}
|
||||
}
|
||||
|
||||
st->silence = !silence;
|
||||
|
||||
if (s->avctx->ch_layout.nb_channels > 1) {
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
float incompat = 0.0f;
|
||||
const float *coeffs1 = st->bands[0][i];
|
||||
const float *coeffs2 = st->bands[1][i];
|
||||
const int range = ff_celt_freq_range[i] << s->bsize_analysis;
|
||||
for (j = 0; j < range; j++)
|
||||
incompat += (coeffs1[j] - coeffs2[j])*(coeffs1[j] - coeffs2[j]);
|
||||
st->stereo[i] = sqrtf(incompat);
|
||||
}
|
||||
}
|
||||
|
||||
for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) {
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
OpusBandExcitation *ex = &s->ex[ch][i];
|
||||
float bp_e = bessel_filter(&s->bfilter_lo[ch][i], st->energy[ch][i]);
|
||||
bp_e = bessel_filter(&s->bfilter_hi[ch][i], bp_e);
|
||||
bp_e *= bp_e;
|
||||
if (bp_e > ex->excitation) {
|
||||
st->change_amp[ch][i] = bp_e - ex->excitation;
|
||||
st->total_change += st->change_amp[ch][i];
|
||||
ex->excitation = ex->excitation_init = bp_e;
|
||||
ex->excitation_dist = 0.0f;
|
||||
}
|
||||
if (ex->excitation > 0.0f) {
|
||||
ex->excitation -= av_clipf((1/expf(ex->excitation_dist)), ex->excitation_init/20, ex->excitation_init/1.09);
|
||||
ex->excitation = FFMAX(ex->excitation, 0.0f);
|
||||
ex->excitation_dist += 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void search_for_change_points(OpusPsyContext *s, float tgt_change,
|
||||
int offset_s, int offset_e, int resolution,
|
||||
int level)
|
||||
{
|
||||
int i;
|
||||
float c_change = 0.0f;
|
||||
if ((offset_e - offset_s) <= resolution)
|
||||
return;
|
||||
for (i = offset_s; i < offset_e; i++) {
|
||||
c_change += s->steps[i]->total_change;
|
||||
if (c_change > tgt_change)
|
||||
break;
|
||||
}
|
||||
if (i == offset_e)
|
||||
return;
|
||||
search_for_change_points(s, tgt_change / 2.0f, offset_s, i + 0, resolution, level + 1);
|
||||
s->inflection_points[s->inflection_points_count++] = i;
|
||||
search_for_change_points(s, tgt_change / 2.0f, i + 1, offset_e, resolution, level + 1);
|
||||
}
|
||||
|
||||
static int flush_silent_frames(OpusPsyContext *s)
|
||||
{
|
||||
int fsize, silent_frames;
|
||||
|
||||
for (silent_frames = 0; silent_frames < s->buffered_steps; silent_frames++)
|
||||
if (!s->steps[silent_frames]->silence)
|
||||
break;
|
||||
if (--silent_frames < 0)
|
||||
return 0;
|
||||
|
||||
for (fsize = CELT_BLOCK_960; fsize > CELT_BLOCK_120; fsize--) {
|
||||
if ((1 << fsize) > silent_frames)
|
||||
continue;
|
||||
s->p.frames = FFMIN(silent_frames / (1 << fsize), 48 >> fsize);
|
||||
s->p.framesize = fsize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main function which decides frame size and frames per current packet */
|
||||
static void psy_output_groups(OpusPsyContext *s)
|
||||
{
|
||||
int max_delay_samples = (s->options->max_delay_ms*s->avctx->sample_rate)/1000;
|
||||
int max_bsize = FFMIN(OPUS_SAMPLES_TO_BLOCK_SIZE(max_delay_samples), CELT_BLOCK_960);
|
||||
|
||||
/* These don't change for now */
|
||||
s->p.mode = OPUS_MODE_CELT;
|
||||
s->p.bandwidth = OPUS_BANDWIDTH_FULLBAND;
|
||||
|
||||
/* Flush silent frames ASAP */
|
||||
if (s->steps[0]->silence && flush_silent_frames(s))
|
||||
return;
|
||||
|
||||
s->p.framesize = FFMIN(max_bsize, CELT_BLOCK_960);
|
||||
s->p.frames = 1;
|
||||
}
|
||||
|
||||
int ff_opus_psy_process(OpusPsyContext *s, OpusPacketInfo *p)
|
||||
{
|
||||
int i;
|
||||
float total_energy_change = 0.0f;
|
||||
|
||||
if (s->buffered_steps < s->max_steps && !s->eof) {
|
||||
const int awin = (1 << s->bsize_analysis);
|
||||
if (++s->steps_to_process >= awin) {
|
||||
step_collect_psy_metrics(s, s->buffered_steps - awin + 1);
|
||||
s->steps_to_process = 0;
|
||||
}
|
||||
if ((++s->buffered_steps) < s->max_steps)
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < s->buffered_steps; i++)
|
||||
total_energy_change += s->steps[i]->total_change;
|
||||
|
||||
search_for_change_points(s, total_energy_change / 2.0f, 0,
|
||||
s->buffered_steps, 1, 0);
|
||||
|
||||
psy_output_groups(s);
|
||||
|
||||
p->frames = s->p.frames;
|
||||
p->framesize = s->p.framesize;
|
||||
p->mode = s->p.mode;
|
||||
p->bandwidth = s->p.bandwidth;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_opus_psy_celt_frame_init(OpusPsyContext *s, CeltFrame *f, int index)
|
||||
{
|
||||
int i, neighbouring_points = 0, start_offset = 0;
|
||||
int radius = (1 << s->p.framesize), step_offset = radius*index;
|
||||
int silence = 1;
|
||||
|
||||
f->start_band = (s->p.mode == OPUS_MODE_HYBRID) ? 17 : 0;
|
||||
f->end_band = ff_celt_band_end[s->p.bandwidth];
|
||||
f->channels = s->avctx->ch_layout.nb_channels;
|
||||
f->size = s->p.framesize;
|
||||
|
||||
for (i = 0; i < (1 << f->size); i++)
|
||||
silence &= s->steps[index*(1 << f->size) + i]->silence;
|
||||
|
||||
f->silence = silence;
|
||||
if (f->silence) {
|
||||
f->framebits = 0; /* Otherwise the silence flag eats up 16(!) bits */
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < s->inflection_points_count; i++) {
|
||||
if (s->inflection_points[i] >= step_offset) {
|
||||
start_offset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = start_offset; i < FFMIN(radius, s->inflection_points_count - start_offset); i++) {
|
||||
if (s->inflection_points[i] < (step_offset + radius)) {
|
||||
neighbouring_points++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Transient flagging */
|
||||
f->transient = neighbouring_points > 0;
|
||||
f->blocks = f->transient ? OPUS_BLOCK_SIZE(s->p.framesize)/CELT_OVERLAP : 1;
|
||||
|
||||
/* Some sane defaults */
|
||||
f->pfilter = 0;
|
||||
f->pf_gain = 0.5f;
|
||||
f->pf_octave = 2;
|
||||
f->pf_period = 1;
|
||||
f->pf_tapset = 2;
|
||||
|
||||
/* More sane defaults */
|
||||
f->tf_select = 0;
|
||||
f->anticollapse = 1;
|
||||
f->alloc_trim = 5;
|
||||
f->skip_band_floor = f->end_band;
|
||||
f->intensity_stereo = f->end_band;
|
||||
f->dual_stereo = 0;
|
||||
f->spread = CELT_SPREAD_NORMAL;
|
||||
memset(f->tf_change, 0, sizeof(int)*CELT_MAX_BANDS);
|
||||
memset(f->alloc_boost, 0, sizeof(int)*CELT_MAX_BANDS);
|
||||
}
|
||||
|
||||
static void celt_gauge_psy_weight(OpusPsyContext *s, OpusPsyStep **start,
|
||||
CeltFrame *f_out)
|
||||
{
|
||||
int i, f, ch;
|
||||
int frame_size = OPUS_BLOCK_SIZE(s->p.framesize);
|
||||
float rate, frame_bits = 0;
|
||||
|
||||
/* Used for the global ROTATE flag */
|
||||
float tonal = 0.0f;
|
||||
|
||||
/* Pseudo-weights */
|
||||
float band_score[CELT_MAX_BANDS] = { 0 };
|
||||
float max_score = 1.0f;
|
||||
|
||||
/* Pass one - one loop around each band, computing unquant stuff */
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
float weight = 0.0f;
|
||||
float tonal_contrib = 0.0f;
|
||||
for (f = 0; f < (1 << s->p.framesize); f++) {
|
||||
weight = start[f]->stereo[i];
|
||||
for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) {
|
||||
weight += start[f]->change_amp[ch][i] + start[f]->tone[ch][i] + start[f]->energy[ch][i];
|
||||
tonal_contrib += start[f]->tone[ch][i];
|
||||
}
|
||||
}
|
||||
tonal += tonal_contrib;
|
||||
band_score[i] = weight;
|
||||
}
|
||||
|
||||
tonal /= (float)CELT_MAX_BANDS;
|
||||
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
if (band_score[i] > max_score)
|
||||
max_score = band_score[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
f_out->alloc_boost[i] = (int)((band_score[i]/max_score)*3.0f);
|
||||
frame_bits += band_score[i]*8.0f;
|
||||
}
|
||||
|
||||
tonal /= 1333136.0f;
|
||||
f_out->spread = av_clip_uintp2(lrintf(tonal), 2);
|
||||
|
||||
rate = ((float)s->avctx->bit_rate) + frame_bits*frame_size*16;
|
||||
rate *= s->lambda;
|
||||
rate /= s->avctx->sample_rate/frame_size;
|
||||
|
||||
f_out->framebits = lrintf(rate);
|
||||
f_out->framebits = FFMIN(f_out->framebits, OPUS_MAX_FRAME_SIZE * 8);
|
||||
f_out->framebits = FFALIGN(f_out->framebits, 8);
|
||||
}
|
||||
|
||||
static int bands_dist(OpusPsyContext *s, CeltFrame *f, float *total_dist)
|
||||
{
|
||||
int i, tdist = 0.0f;
|
||||
OpusRangeCoder dump;
|
||||
|
||||
ff_opus_rc_enc_init(&dump);
|
||||
ff_celt_bitalloc(f, &dump, 1);
|
||||
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
float bits = 0.0f;
|
||||
float dist = pvq_band_cost(f->pvq, f, &dump, i, &bits, s->lambda);
|
||||
tdist += dist;
|
||||
}
|
||||
|
||||
*total_dist = tdist;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void celt_search_for_dual_stereo(OpusPsyContext *s, CeltFrame *f)
|
||||
{
|
||||
float td1, td2;
|
||||
f->dual_stereo = 0;
|
||||
|
||||
if (s->avctx->ch_layout.nb_channels < 2)
|
||||
return;
|
||||
|
||||
bands_dist(s, f, &td1);
|
||||
f->dual_stereo = 1;
|
||||
bands_dist(s, f, &td2);
|
||||
|
||||
f->dual_stereo = td2 < td1;
|
||||
s->dual_stereo_used += td2 < td1;
|
||||
}
|
||||
|
||||
static void celt_search_for_intensity(OpusPsyContext *s, CeltFrame *f)
|
||||
{
|
||||
int i, best_band = CELT_MAX_BANDS - 1;
|
||||
float dist, best_dist = FLT_MAX;
|
||||
/* TODO: fix, make some heuristic up here using the lambda value */
|
||||
float end_band = 0;
|
||||
|
||||
if (s->avctx->ch_layout.nb_channels < 2)
|
||||
return;
|
||||
|
||||
for (i = f->end_band; i >= end_band; i--) {
|
||||
f->intensity_stereo = i;
|
||||
bands_dist(s, f, &dist);
|
||||
if (best_dist > dist) {
|
||||
best_dist = dist;
|
||||
best_band = i;
|
||||
}
|
||||
}
|
||||
|
||||
f->intensity_stereo = best_band;
|
||||
s->avg_is_band = (s->avg_is_band + f->intensity_stereo)/2.0f;
|
||||
}
|
||||
|
||||
static int celt_search_for_tf(OpusPsyContext *s, OpusPsyStep **start, CeltFrame *f)
|
||||
{
|
||||
int i, j, k, cway, config[2][CELT_MAX_BANDS] = { { 0 } };
|
||||
float score[2] = { 0 };
|
||||
|
||||
for (cway = 0; cway < 2; cway++) {
|
||||
int mag[2];
|
||||
int base = f->transient ? 120 : 960;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
int c = ff_celt_tf_select[f->size][f->transient][cway][i];
|
||||
mag[i] = c < 0 ? base >> FFABS(c) : base << FFABS(c);
|
||||
}
|
||||
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
float iscore0 = 0.0f;
|
||||
float iscore1 = 0.0f;
|
||||
for (j = 0; j < (1 << f->size); j++) {
|
||||
for (k = 0; k < s->avctx->ch_layout.nb_channels; k++) {
|
||||
iscore0 += start[j]->tone[k][i]*start[j]->change_amp[k][i]/mag[0];
|
||||
iscore1 += start[j]->tone[k][i]*start[j]->change_amp[k][i]/mag[1];
|
||||
}
|
||||
}
|
||||
config[cway][i] = FFABS(iscore0 - 1.0f) < FFABS(iscore1 - 1.0f);
|
||||
score[cway] += config[cway][i] ? iscore1 : iscore0;
|
||||
}
|
||||
}
|
||||
|
||||
f->tf_select = score[0] < score[1];
|
||||
memcpy(f->tf_change, config[f->tf_select], sizeof(int)*CELT_MAX_BANDS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_opus_psy_celt_frame_process(OpusPsyContext *s, CeltFrame *f, int index)
|
||||
{
|
||||
int start_transient_flag = f->transient;
|
||||
OpusPsyStep **start = &s->steps[index * (1 << s->p.framesize)];
|
||||
|
||||
if (f->silence)
|
||||
return 0;
|
||||
|
||||
celt_gauge_psy_weight(s, start, f);
|
||||
celt_search_for_intensity(s, f);
|
||||
celt_search_for_dual_stereo(s, f);
|
||||
celt_search_for_tf(s, start, f);
|
||||
|
||||
if (f->transient != start_transient_flag) {
|
||||
f->blocks = f->transient ? OPUS_BLOCK_SIZE(s->p.framesize)/CELT_OVERLAP : 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_opus_psy_postencode_update(OpusPsyContext *s, CeltFrame *f)
|
||||
{
|
||||
int i, frame_size = OPUS_BLOCK_SIZE(s->p.framesize);
|
||||
int steps_out = s->p.frames*(frame_size/120);
|
||||
void *tmp[FF_BUFQUEUE_SIZE];
|
||||
float ideal_fbits;
|
||||
|
||||
for (i = 0; i < steps_out; i++)
|
||||
memset(s->steps[i], 0, sizeof(OpusPsyStep));
|
||||
|
||||
for (i = 0; i < s->max_steps; i++)
|
||||
tmp[i] = s->steps[i];
|
||||
|
||||
for (i = 0; i < s->max_steps; i++) {
|
||||
const int i_new = i - steps_out;
|
||||
s->steps[i_new < 0 ? s->max_steps + i_new : i_new] = tmp[i];
|
||||
}
|
||||
|
||||
for (i = steps_out; i < s->buffered_steps; i++)
|
||||
s->steps[i]->index -= steps_out;
|
||||
|
||||
ideal_fbits = s->avctx->bit_rate/(s->avctx->sample_rate/frame_size);
|
||||
|
||||
for (i = 0; i < s->p.frames; i++) {
|
||||
s->avg_is_band += f[i].intensity_stereo;
|
||||
s->lambda *= ideal_fbits / f[i].framebits;
|
||||
}
|
||||
|
||||
s->avg_is_band /= (s->p.frames + 1);
|
||||
|
||||
s->steps_to_process = 0;
|
||||
s->buffered_steps -= steps_out;
|
||||
s->total_packets_out += s->p.frames;
|
||||
s->inflection_points_count = 0;
|
||||
}
|
||||
|
||||
av_cold int ff_opus_psy_init(OpusPsyContext *s, AVCodecContext *avctx,
|
||||
struct FFBufQueue *bufqueue, OpusEncOptions *options)
|
||||
{
|
||||
int i, ch, ret;
|
||||
|
||||
s->lambda = 1.0f;
|
||||
s->options = options;
|
||||
s->avctx = avctx;
|
||||
s->bufqueue = bufqueue;
|
||||
s->max_steps = ceilf(s->options->max_delay_ms/2.5f);
|
||||
s->bsize_analysis = CELT_BLOCK_960;
|
||||
s->avg_is_band = CELT_MAX_BANDS - 1;
|
||||
s->inflection_points_count = 0;
|
||||
|
||||
s->inflection_points = av_mallocz(sizeof(*s->inflection_points)*s->max_steps);
|
||||
if (!s->inflection_points) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s->dsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
|
||||
if (!s->dsp) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) {
|
||||
for (i = 0; i < CELT_MAX_BANDS; i++) {
|
||||
bessel_init(&s->bfilter_hi[ch][i], 1.0f, 19.0f, 100.0f, 1);
|
||||
bessel_init(&s->bfilter_lo[ch][i], 1.0f, 20.0f, 100.0f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < s->max_steps; i++) {
|
||||
s->steps[i] = av_mallocz(sizeof(OpusPsyStep));
|
||||
if (!s->steps[i]) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < CELT_BLOCK_NB; i++) {
|
||||
float tmp;
|
||||
const int len = OPUS_BLOCK_SIZE(i);
|
||||
const float scale = 68 << (CELT_BLOCK_NB - 1 - i);
|
||||
s->window[i] = av_malloc(2*len*sizeof(float));
|
||||
if (!s->window[i]) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
generate_window_func(s->window[i], 2*len, WFUNC_SINE, &tmp);
|
||||
ret = av_tx_init(&s->mdct[i], &s->mdct_fn[i], AV_TX_FLOAT_MDCT,
|
||||
0, 15 << (i + 3), &scale, 0);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
av_freep(&s->inflection_points);
|
||||
av_freep(&s->dsp);
|
||||
|
||||
for (i = 0; i < CELT_BLOCK_NB; i++) {
|
||||
av_tx_uninit(&s->mdct[i]);
|
||||
av_freep(&s->window[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < s->max_steps; i++)
|
||||
av_freep(&s->steps[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ff_opus_psy_signal_eof(OpusPsyContext *s)
|
||||
{
|
||||
s->eof = 1;
|
||||
}
|
||||
|
||||
av_cold int ff_opus_psy_end(OpusPsyContext *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
av_freep(&s->inflection_points);
|
||||
av_freep(&s->dsp);
|
||||
|
||||
for (i = 0; i < CELT_BLOCK_NB; i++) {
|
||||
av_tx_uninit(&s->mdct[i]);
|
||||
av_freep(&s->window[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < s->max_steps; i++)
|
||||
av_freep(&s->steps[i]);
|
||||
|
||||
av_log(s->avctx, AV_LOG_INFO, "Average Intensity Stereo band: %0.1f\n", s->avg_is_band);
|
||||
av_log(s->avctx, AV_LOG_INFO, "Dual Stereo used: %0.2f%%\n", ((float)s->dual_stereo_used/s->total_packets_out)*100.0f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Opus encoder
|
||||
* Copyright (c) 2017 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_ENC_PSY_H
|
||||
#define AVCODEC_OPUS_ENC_PSY_H
|
||||
|
||||
#include "libavutil/tx.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
|
||||
#include "enc.h"
|
||||
#include "celt.h"
|
||||
#include "enc_utils.h"
|
||||
|
||||
/* Each step is 2.5ms */
|
||||
typedef struct OpusPsyStep {
|
||||
int index; /* Current index */
|
||||
int silence;
|
||||
float energy[OPUS_MAX_CHANNELS][CELT_MAX_BANDS]; /* Masking effects included */
|
||||
float tone[OPUS_MAX_CHANNELS][CELT_MAX_BANDS]; /* Tonality */
|
||||
float stereo[CELT_MAX_BANDS]; /* IS/MS compatibility */
|
||||
float change_amp[OPUS_MAX_CHANNELS][CELT_MAX_BANDS]; /* Jump over last frame */
|
||||
float total_change; /* Total change */
|
||||
|
||||
float *bands[OPUS_MAX_CHANNELS][CELT_MAX_BANDS];
|
||||
float coeffs[OPUS_MAX_CHANNELS][OPUS_BLOCK_SIZE(CELT_BLOCK_960)];
|
||||
} OpusPsyStep;
|
||||
|
||||
typedef struct OpusBandExcitation {
|
||||
float excitation;
|
||||
float excitation_dist;
|
||||
float excitation_init;
|
||||
} OpusBandExcitation;
|
||||
|
||||
typedef struct OpusPsyContext {
|
||||
AVCodecContext *avctx;
|
||||
AVFloatDSPContext *dsp;
|
||||
struct FFBufQueue *bufqueue;
|
||||
OpusEncOptions *options;
|
||||
|
||||
OpusBandExcitation ex[OPUS_MAX_CHANNELS][CELT_MAX_BANDS];
|
||||
FFBesselFilter bfilter_lo[OPUS_MAX_CHANNELS][CELT_MAX_BANDS];
|
||||
FFBesselFilter bfilter_hi[OPUS_MAX_CHANNELS][CELT_MAX_BANDS];
|
||||
|
||||
OpusPsyStep *steps[FF_BUFQUEUE_SIZE + 1];
|
||||
int max_steps;
|
||||
|
||||
float *window[CELT_BLOCK_NB];
|
||||
AVTXContext *mdct[CELT_BLOCK_NB];
|
||||
av_tx_fn mdct_fn[CELT_BLOCK_NB];
|
||||
int bsize_analysis;
|
||||
|
||||
DECLARE_ALIGNED(32, float, scratch)[2048];
|
||||
|
||||
/* Stats */
|
||||
float avg_is_band;
|
||||
int64_t dual_stereo_used;
|
||||
int64_t total_packets_out;
|
||||
|
||||
/* State */
|
||||
OpusPacketInfo p;
|
||||
int buffered_steps;
|
||||
int steps_to_process;
|
||||
int eof;
|
||||
float lambda;
|
||||
int *inflection_points;
|
||||
int inflection_points_count;
|
||||
} OpusPsyContext;
|
||||
|
||||
int ff_opus_psy_process (OpusPsyContext *s, OpusPacketInfo *p);
|
||||
void ff_opus_psy_celt_frame_init (OpusPsyContext *s, CeltFrame *f, int index);
|
||||
int ff_opus_psy_celt_frame_process(OpusPsyContext *s, CeltFrame *f, int index);
|
||||
void ff_opus_psy_postencode_update (OpusPsyContext *s, CeltFrame *f);
|
||||
|
||||
int ff_opus_psy_init(OpusPsyContext *s, AVCodecContext *avctx,
|
||||
struct FFBufQueue *bufqueue, OpusEncOptions *options);
|
||||
void ff_opus_psy_signal_eof(OpusPsyContext *s);
|
||||
int ff_opus_psy_end(OpusPsyContext *s);
|
||||
|
||||
#endif /* AVCODEC_OPUS_ENC_PSY_H */
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Opus encoder
|
||||
* Copyright (c) 2017 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_ENC_UTILS_H
|
||||
#define AVCODEC_OPUS_ENC_UTILS_H
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "opus.h"
|
||||
|
||||
typedef struct FFBesselFilter {
|
||||
float a[3];
|
||||
float b[2];
|
||||
float x[3];
|
||||
float y[3];
|
||||
} FFBesselFilter;
|
||||
|
||||
/* Fills the coefficients, returns 1 if filter will be unstable */
|
||||
static inline int bessel_reinit(FFBesselFilter *s, float n, float f0, float fs,
|
||||
int highpass)
|
||||
{
|
||||
int unstable;
|
||||
float c, cfreq, w0, k1, k2;
|
||||
|
||||
if (!highpass) {
|
||||
c = (1.0f/sqrtf(sqrtf(pow(2.0f, 1.0f/n) - 3.0f/4.0f) - 0.5f))/sqrtf(3.0f);
|
||||
cfreq = c*f0/fs;
|
||||
unstable = (cfreq <= 0.0f || cfreq >= 1.0f/4.0f);
|
||||
} else {
|
||||
c = sqrtf(3.0f)*sqrtf(sqrtf(pow(2.0f, 1.0f/n) - 3.0f/4.0f) - 0.5f);
|
||||
cfreq = 0.5f - c*f0/fs;
|
||||
unstable = (cfreq <= 3.0f/8.0f || cfreq >= 1.0f/2.0f);
|
||||
}
|
||||
|
||||
w0 = tanf(M_PI*cfreq);
|
||||
k1 = 3.0f * w0;
|
||||
k2 = 3.0f * w0;
|
||||
|
||||
s->a[0] = k2/(1.0f + k1 + k2);
|
||||
s->a[1] = 2.0f * s->a[0];
|
||||
s->a[2] = s->a[0];
|
||||
s->b[0] = 2.0f * s->a[0] * (1.0f/k2 - 1.0f);
|
||||
s->b[1] = 1.0f - (s->a[0] + s->a[1] + s->a[2] + s->b[0]);
|
||||
|
||||
if (highpass) {
|
||||
s->a[1] *= -1;
|
||||
s->b[0] *= -1;
|
||||
}
|
||||
|
||||
return unstable;
|
||||
}
|
||||
|
||||
static inline int bessel_init(FFBesselFilter *s, float n, float f0, float fs,
|
||||
int highpass)
|
||||
{
|
||||
memset(s, 0, sizeof(FFBesselFilter));
|
||||
return bessel_reinit(s, n, f0, fs, highpass);
|
||||
}
|
||||
|
||||
static inline float bessel_filter(FFBesselFilter *s, float x)
|
||||
{
|
||||
s->x[2] = s->x[1];
|
||||
s->x[1] = s->x[0];
|
||||
s->x[0] = x;
|
||||
s->y[2] = s->y[1];
|
||||
s->y[1] = s->y[0];
|
||||
s->y[0] = s->a[0]*s->x[0] + s->a[1]*s->x[1] + s->a[2]*s->x[2] + s->b[0]*s->y[1] + s->b[1]*s->y[2];
|
||||
return s->y[0];
|
||||
}
|
||||
|
||||
#endif /* AVCODEC_OPUS_ENC_UTILS_H */
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Opus common header
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_OPUS_H
|
||||
#define AVCODEC_OPUS_OPUS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define OPUS_MAX_FRAME_SIZE 1275
|
||||
#define OPUS_MAX_FRAMES 48
|
||||
#define OPUS_MAX_PACKET_DUR 5760
|
||||
|
||||
#define OPUS_TS_HEADER 0x7FE0 // 0x3ff (11 bits)
|
||||
#define OPUS_TS_MASK 0xFFE0 // top 11 bits
|
||||
|
||||
static const uint8_t opus_default_extradata[30] = {
|
||||
'O', 'p', 'u', 's', 'H', 'e', 'a', 'd',
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
enum OpusMode {
|
||||
OPUS_MODE_SILK,
|
||||
OPUS_MODE_HYBRID,
|
||||
OPUS_MODE_CELT,
|
||||
|
||||
OPUS_MODE_NB
|
||||
};
|
||||
|
||||
enum OpusBandwidth {
|
||||
OPUS_BANDWIDTH_NARROWBAND,
|
||||
OPUS_BANDWIDTH_MEDIUMBAND,
|
||||
OPUS_BANDWIDTH_WIDEBAND,
|
||||
OPUS_BANDWIDTH_SUPERWIDEBAND,
|
||||
OPUS_BANDWIDTH_FULLBAND,
|
||||
|
||||
OPUS_BANDWITH_NB
|
||||
};
|
||||
|
||||
#endif /* AVCODEC_OPUS_OPUS_H */
|
||||
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
*
|
||||
* 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
|
||||
* Opus decoder/parser shared code
|
||||
*/
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/log.h"
|
||||
#include "libavutil/mem.h"
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "internal.h"
|
||||
#include "mathops.h"
|
||||
#include "opus.h"
|
||||
#include "parse.h"
|
||||
#include "vorbis_data.h"
|
||||
|
||||
static const uint16_t opus_frame_duration[32] = {
|
||||
480, 960, 1920, 2880,
|
||||
480, 960, 1920, 2880,
|
||||
480, 960, 1920, 2880,
|
||||
480, 960,
|
||||
480, 960,
|
||||
120, 240, 480, 960,
|
||||
120, 240, 480, 960,
|
||||
120, 240, 480, 960,
|
||||
120, 240, 480, 960,
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a 1- or 2-byte frame length
|
||||
*/
|
||||
static inline int xiph_lacing_16bit(const uint8_t **ptr, const uint8_t *end)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (*ptr >= end)
|
||||
return AVERROR_INVALIDDATA;
|
||||
val = *(*ptr)++;
|
||||
if (val >= 252) {
|
||||
if (*ptr >= end)
|
||||
return AVERROR_INVALIDDATA;
|
||||
val += 4 * *(*ptr)++;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a multi-byte length (used for code 3 packet padding size)
|
||||
*/
|
||||
static inline int xiph_lacing_full(const uint8_t **ptr, const uint8_t *end)
|
||||
{
|
||||
int val = 0;
|
||||
int next;
|
||||
|
||||
while (1) {
|
||||
if (*ptr >= end || val > INT_MAX - 254)
|
||||
return AVERROR_INVALIDDATA;
|
||||
next = *(*ptr)++;
|
||||
val += next;
|
||||
if (next < 255)
|
||||
break;
|
||||
else
|
||||
val--;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Opus packet info from raw packet data
|
||||
*/
|
||||
int ff_opus_parse_packet(OpusPacket *pkt, const uint8_t *buf, int buf_size,
|
||||
int self_delimiting)
|
||||
{
|
||||
const uint8_t *ptr = buf;
|
||||
const uint8_t *end = buf + buf_size;
|
||||
int padding = 0;
|
||||
int frame_bytes, i;
|
||||
|
||||
if (buf_size < 1)
|
||||
goto fail;
|
||||
|
||||
/* TOC byte */
|
||||
i = *ptr++;
|
||||
pkt->code = (i ) & 0x3;
|
||||
pkt->stereo = (i >> 2) & 0x1;
|
||||
pkt->config = (i >> 3) & 0x1F;
|
||||
|
||||
/* code 2 and code 3 packets have at least 1 byte after the TOC */
|
||||
if (pkt->code >= 2 && buf_size < 2)
|
||||
goto fail;
|
||||
|
||||
switch (pkt->code) {
|
||||
case 0:
|
||||
/* 1 frame */
|
||||
pkt->frame_count = 1;
|
||||
pkt->vbr = 0;
|
||||
|
||||
if (self_delimiting) {
|
||||
int len = xiph_lacing_16bit(&ptr, end);
|
||||
if (len < 0 || len > end - ptr)
|
||||
goto fail;
|
||||
end = ptr + len;
|
||||
buf_size = end - buf;
|
||||
}
|
||||
|
||||
frame_bytes = end - ptr;
|
||||
if (frame_bytes > OPUS_MAX_FRAME_SIZE)
|
||||
goto fail;
|
||||
pkt->frame_offset[0] = ptr - buf;
|
||||
pkt->frame_size[0] = frame_bytes;
|
||||
break;
|
||||
case 1:
|
||||
/* 2 frames, equal size */
|
||||
pkt->frame_count = 2;
|
||||
pkt->vbr = 0;
|
||||
|
||||
if (self_delimiting) {
|
||||
int len = xiph_lacing_16bit(&ptr, end);
|
||||
if (len < 0 || 2 * len > end - ptr)
|
||||
goto fail;
|
||||
end = ptr + 2 * len;
|
||||
buf_size = end - buf;
|
||||
}
|
||||
|
||||
frame_bytes = end - ptr;
|
||||
if (frame_bytes & 1 || frame_bytes >> 1 > OPUS_MAX_FRAME_SIZE)
|
||||
goto fail;
|
||||
pkt->frame_offset[0] = ptr - buf;
|
||||
pkt->frame_size[0] = frame_bytes >> 1;
|
||||
pkt->frame_offset[1] = pkt->frame_offset[0] + pkt->frame_size[0];
|
||||
pkt->frame_size[1] = frame_bytes >> 1;
|
||||
break;
|
||||
case 2:
|
||||
/* 2 frames, different sizes */
|
||||
pkt->frame_count = 2;
|
||||
pkt->vbr = 1;
|
||||
|
||||
/* read 1st frame size */
|
||||
frame_bytes = xiph_lacing_16bit(&ptr, end);
|
||||
if (frame_bytes < 0)
|
||||
goto fail;
|
||||
|
||||
if (self_delimiting) {
|
||||
int len = xiph_lacing_16bit(&ptr, end);
|
||||
if (len < 0 || len + frame_bytes > end - ptr)
|
||||
goto fail;
|
||||
end = ptr + frame_bytes + len;
|
||||
buf_size = end - buf;
|
||||
}
|
||||
|
||||
pkt->frame_offset[0] = ptr - buf;
|
||||
pkt->frame_size[0] = frame_bytes;
|
||||
|
||||
/* calculate 2nd frame size */
|
||||
frame_bytes = end - ptr - pkt->frame_size[0];
|
||||
if (frame_bytes < 0 || frame_bytes > OPUS_MAX_FRAME_SIZE)
|
||||
goto fail;
|
||||
pkt->frame_offset[1] = pkt->frame_offset[0] + pkt->frame_size[0];
|
||||
pkt->frame_size[1] = frame_bytes;
|
||||
break;
|
||||
case 3:
|
||||
/* 1 to 48 frames, can be different sizes */
|
||||
i = *ptr++;
|
||||
pkt->frame_count = (i ) & 0x3F;
|
||||
padding = (i >> 6) & 0x01;
|
||||
pkt->vbr = (i >> 7) & 0x01;
|
||||
|
||||
if (pkt->frame_count == 0 || pkt->frame_count > OPUS_MAX_FRAMES)
|
||||
goto fail;
|
||||
|
||||
/* read padding size */
|
||||
if (padding) {
|
||||
padding = xiph_lacing_full(&ptr, end);
|
||||
if (padding < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* read frame sizes */
|
||||
if (pkt->vbr) {
|
||||
/* for VBR, all frames except the final one have their size coded
|
||||
in the bitstream. the last frame size is implicit. */
|
||||
int total_bytes = 0;
|
||||
for (i = 0; i < pkt->frame_count - 1; i++) {
|
||||
frame_bytes = xiph_lacing_16bit(&ptr, end);
|
||||
if (frame_bytes < 0)
|
||||
goto fail;
|
||||
pkt->frame_size[i] = frame_bytes;
|
||||
total_bytes += frame_bytes;
|
||||
}
|
||||
|
||||
if (self_delimiting) {
|
||||
int len = xiph_lacing_16bit(&ptr, end);
|
||||
if (len < 0 || len + total_bytes + padding > end - ptr)
|
||||
goto fail;
|
||||
end = ptr + total_bytes + len + padding;
|
||||
buf_size = end - buf;
|
||||
}
|
||||
|
||||
frame_bytes = end - ptr - padding;
|
||||
if (total_bytes > frame_bytes)
|
||||
goto fail;
|
||||
pkt->frame_offset[0] = ptr - buf;
|
||||
for (i = 1; i < pkt->frame_count; i++)
|
||||
pkt->frame_offset[i] = pkt->frame_offset[i-1] + pkt->frame_size[i-1];
|
||||
pkt->frame_size[pkt->frame_count-1] = frame_bytes - total_bytes;
|
||||
} else {
|
||||
/* for CBR, the remaining packet bytes are divided evenly between
|
||||
the frames */
|
||||
if (self_delimiting) {
|
||||
frame_bytes = xiph_lacing_16bit(&ptr, end);
|
||||
if (frame_bytes < 0 || pkt->frame_count * frame_bytes + padding > end - ptr)
|
||||
goto fail;
|
||||
end = ptr + pkt->frame_count * frame_bytes + padding;
|
||||
buf_size = end - buf;
|
||||
} else {
|
||||
frame_bytes = end - ptr - padding;
|
||||
if (frame_bytes % pkt->frame_count ||
|
||||
frame_bytes / pkt->frame_count > OPUS_MAX_FRAME_SIZE)
|
||||
goto fail;
|
||||
frame_bytes /= pkt->frame_count;
|
||||
}
|
||||
|
||||
pkt->frame_offset[0] = ptr - buf;
|
||||
pkt->frame_size[0] = frame_bytes;
|
||||
for (i = 1; i < pkt->frame_count; i++) {
|
||||
pkt->frame_offset[i] = pkt->frame_offset[i-1] + pkt->frame_size[i-1];
|
||||
pkt->frame_size[i] = frame_bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pkt->packet_size = buf_size;
|
||||
pkt->data_size = pkt->packet_size - padding;
|
||||
|
||||
/* total packet duration cannot be larger than 120ms */
|
||||
pkt->frame_duration = opus_frame_duration[pkt->config];
|
||||
if (pkt->frame_duration * pkt->frame_count > OPUS_MAX_PACKET_DUR)
|
||||
goto fail;
|
||||
|
||||
/* set mode and bandwidth */
|
||||
if (pkt->config < 12) {
|
||||
pkt->mode = OPUS_MODE_SILK;
|
||||
pkt->bandwidth = pkt->config >> 2;
|
||||
} else if (pkt->config < 16) {
|
||||
pkt->mode = OPUS_MODE_HYBRID;
|
||||
pkt->bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND + (pkt->config >= 14);
|
||||
} else {
|
||||
pkt->mode = OPUS_MODE_CELT;
|
||||
pkt->bandwidth = (pkt->config - 16) >> 2;
|
||||
/* skip medium band */
|
||||
if (pkt->bandwidth)
|
||||
pkt->bandwidth++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
memset(pkt, 0, sizeof(*pkt));
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
static int channel_reorder_vorbis(int nb_channels, int channel_idx)
|
||||
{
|
||||
return ff_vorbis_channel_layout_offsets[nb_channels - 1][channel_idx];
|
||||
}
|
||||
|
||||
static int channel_reorder_unknown(int nb_channels, int channel_idx)
|
||||
{
|
||||
return channel_idx;
|
||||
}
|
||||
|
||||
av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
|
||||
OpusParseContext *s)
|
||||
{
|
||||
static const uint8_t default_channel_map[2] = { 0, 1 };
|
||||
|
||||
int (*channel_reorder)(int, int) = channel_reorder_unknown;
|
||||
int channels = avctx->ch_layout.nb_channels;
|
||||
|
||||
const uint8_t *extradata, *channel_map;
|
||||
int extradata_size;
|
||||
int version, map_type, streams, stereo_streams, i, j, ret;
|
||||
AVChannelLayout layout = { 0 };
|
||||
|
||||
if (!avctx->extradata) {
|
||||
if (channels > 2) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Multichannel configuration without extradata.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
extradata = opus_default_extradata;
|
||||
extradata_size = sizeof(opus_default_extradata);
|
||||
} else {
|
||||
extradata = avctx->extradata;
|
||||
extradata_size = avctx->extradata_size;
|
||||
}
|
||||
|
||||
if (extradata_size < 19) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid extradata size: %d\n",
|
||||
extradata_size);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
version = extradata[8];
|
||||
if (version > 15) {
|
||||
avpriv_request_sample(avctx, "Extradata version %d", version);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
avctx->delay = AV_RL16(extradata + 10);
|
||||
if (avctx->internal)
|
||||
avctx->internal->skip_samples = avctx->delay;
|
||||
|
||||
channels = avctx->extradata ? extradata[9] : (channels == 1) ? 1 : 2;
|
||||
if (!channels) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Zero channel count specified in the extradata\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
s->gain_i = AV_RL16(extradata + 16);
|
||||
|
||||
map_type = extradata[18];
|
||||
if (!map_type) {
|
||||
if (channels > 2) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Channel mapping 0 is only specified for up to 2 channels\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
layout = (channels == 1) ? (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO :
|
||||
(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
|
||||
streams = 1;
|
||||
stereo_streams = channels - 1;
|
||||
channel_map = default_channel_map;
|
||||
} else if (map_type == 1 || map_type == 2 || map_type == 255) {
|
||||
if (extradata_size < 21 + channels) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid extradata size: %d\n",
|
||||
extradata_size);
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
streams = extradata[19];
|
||||
stereo_streams = extradata[20];
|
||||
if (!streams || stereo_streams > streams ||
|
||||
streams + stereo_streams > 255) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Invalid stream/stereo stream count: %d/%d\n", streams, stereo_streams);
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (map_type == 1) {
|
||||
if (channels > 8) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Channel mapping 1 is only specified for up to 8 channels\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
av_channel_layout_copy(&layout, &ff_vorbis_ch_layouts[channels - 1]);
|
||||
channel_reorder = channel_reorder_vorbis;
|
||||
} else if (map_type == 2) {
|
||||
int ambisonic_order = ff_sqrt(channels) - 1;
|
||||
if (channels != ((ambisonic_order + 1) * (ambisonic_order + 1)) &&
|
||||
channels != ((ambisonic_order + 1) * (ambisonic_order + 1) + 2)) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Channel mapping 2 is only specified for channel counts"
|
||||
" which can be written as (n + 1)^2 or (n + 1)^2 + 2"
|
||||
" for nonnegative integer n\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
if (channels > 227) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Too many channels\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
layout.order = AV_CHANNEL_ORDER_AMBISONIC;
|
||||
layout.nb_channels = channels;
|
||||
if (channels != ((ambisonic_order + 1) * (ambisonic_order + 1)))
|
||||
layout.u.mask = AV_CH_LAYOUT_STEREO;
|
||||
} else {
|
||||
layout.order = AV_CHANNEL_ORDER_UNSPEC;
|
||||
layout.nb_channels = channels;
|
||||
}
|
||||
|
||||
channel_map = extradata + 21;
|
||||
} else {
|
||||
avpriv_request_sample(avctx, "Mapping type %d", map_type);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
s->channel_maps = av_calloc(channels, sizeof(*s->channel_maps));
|
||||
if (!s->channel_maps) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < channels; i++) {
|
||||
ChannelMap *map = &s->channel_maps[i];
|
||||
uint8_t idx = channel_map[channel_reorder(channels, i)];
|
||||
|
||||
if (idx == 255) {
|
||||
map->silence = 1;
|
||||
continue;
|
||||
} else if (idx >= streams + stereo_streams) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Invalid channel map for output channel %d: %d\n", i, idx);
|
||||
av_freep(&s->channel_maps);
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* check that we did not see this index yet */
|
||||
map->copy = 0;
|
||||
for (j = 0; j < i; j++)
|
||||
if (channel_map[channel_reorder(channels, j)] == idx) {
|
||||
map->copy = 1;
|
||||
map->copy_idx = j;
|
||||
break;
|
||||
}
|
||||
|
||||
if (idx < 2 * stereo_streams) {
|
||||
map->stream_idx = idx / 2;
|
||||
map->channel_idx = idx & 1;
|
||||
} else {
|
||||
map->stream_idx = idx - stereo_streams;
|
||||
map->channel_idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = av_channel_layout_copy(&avctx->ch_layout, &layout);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
s->nb_streams = streams;
|
||||
s->nb_stereo_streams = stereo_streams;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
av_channel_layout_uninit(&layout);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Opus decoder/parser common functions and structures
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_PARSE_H
|
||||
#define AVCODEC_OPUS_PARSE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "opus.h"
|
||||
|
||||
typedef struct OpusPacket {
|
||||
int packet_size; /**< packet size */
|
||||
int data_size; /**< size of the useful data -- packet size - padding */
|
||||
int code; /**< packet code: specifies the frame layout */
|
||||
int stereo; /**< whether this packet is mono or stereo */
|
||||
int vbr; /**< vbr flag */
|
||||
int config; /**< configuration: tells the audio mode,
|
||||
** bandwidth, and frame duration */
|
||||
int frame_count; /**< frame count */
|
||||
int frame_offset[OPUS_MAX_FRAMES]; /**< frame offsets */
|
||||
int frame_size[OPUS_MAX_FRAMES]; /**< frame sizes */
|
||||
int frame_duration; /**< frame duration, in samples @ 48kHz */
|
||||
enum OpusMode mode; /**< mode */
|
||||
enum OpusBandwidth bandwidth; /**< bandwidth */
|
||||
} OpusPacket;
|
||||
|
||||
// a mapping between an opus stream and an output channel
|
||||
typedef struct ChannelMap {
|
||||
int stream_idx;
|
||||
int channel_idx;
|
||||
|
||||
// when a single decoded channel is mapped to multiple output channels, we
|
||||
// write to the first output directly and copy from it to the others
|
||||
// this field is set to 1 for those copied output channels
|
||||
int copy;
|
||||
// this is the index of the output channel to copy from
|
||||
int copy_idx;
|
||||
|
||||
// this channel is silent
|
||||
int silence;
|
||||
} ChannelMap;
|
||||
|
||||
typedef struct OpusParseContext {
|
||||
int nb_streams;
|
||||
int nb_stereo_streams;
|
||||
|
||||
int16_t gain_i;
|
||||
|
||||
ChannelMap *channel_maps;
|
||||
} OpusParseContext;
|
||||
|
||||
int ff_opus_parse_packet(OpusPacket *pkt, const uint8_t *buf, int buf_size,
|
||||
int self_delimited);
|
||||
|
||||
int ff_opus_parse_extradata(AVCodecContext *avctx, OpusParseContext *s);
|
||||
|
||||
#endif /* AVCODEC_OPUS_PARSE_H */
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
*
|
||||
* 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
|
||||
* Opus parser
|
||||
*
|
||||
* Determines the duration for each packet.
|
||||
*/
|
||||
|
||||
#include "libavutil/mem.h"
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
#include "opus.h"
|
||||
#include "parse.h"
|
||||
#include "parser.h"
|
||||
|
||||
typedef struct OpusParserContext {
|
||||
ParseContext pc;
|
||||
OpusParseContext ctx;
|
||||
OpusPacket pkt;
|
||||
int extradata_parsed;
|
||||
int ts_framing;
|
||||
} OpusParserContext;
|
||||
|
||||
static const uint8_t *parse_opus_ts_header(const uint8_t *start, int *payload_len, int buf_len)
|
||||
{
|
||||
const uint8_t *buf = start + 1;
|
||||
int start_trim_flag, end_trim_flag, control_extension_flag, control_extension_length;
|
||||
uint8_t flags;
|
||||
uint64_t payload_len_tmp;
|
||||
|
||||
GetByteContext gb;
|
||||
bytestream2_init(&gb, buf, buf_len);
|
||||
|
||||
flags = bytestream2_get_byte(&gb);
|
||||
start_trim_flag = (flags >> 4) & 1;
|
||||
end_trim_flag = (flags >> 3) & 1;
|
||||
control_extension_flag = (flags >> 2) & 1;
|
||||
|
||||
payload_len_tmp = *payload_len = 0;
|
||||
while (bytestream2_peek_byte(&gb) == 0xff)
|
||||
payload_len_tmp += bytestream2_get_byte(&gb);
|
||||
|
||||
payload_len_tmp += bytestream2_get_byte(&gb);
|
||||
|
||||
if (start_trim_flag)
|
||||
bytestream2_skip(&gb, 2);
|
||||
if (end_trim_flag)
|
||||
bytestream2_skip(&gb, 2);
|
||||
if (control_extension_flag) {
|
||||
control_extension_length = bytestream2_get_byte(&gb);
|
||||
bytestream2_skip(&gb, control_extension_length);
|
||||
}
|
||||
|
||||
if (bytestream2_tell(&gb) + payload_len_tmp > buf_len)
|
||||
return NULL;
|
||||
|
||||
*payload_len = payload_len_tmp;
|
||||
|
||||
return buf + bytestream2_tell(&gb);
|
||||
}
|
||||
|
||||
static int set_frame_duration(AVCodecParserContext *ctx, AVCodecContext *avctx,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
OpusParserContext *s = ctx->priv_data;
|
||||
|
||||
if (ff_opus_parse_packet(&s->pkt, buf, buf_size, s->ctx.nb_streams > 1) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error parsing Opus packet header.\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
ctx->duration = s->pkt.frame_count * s->pkt.frame_duration;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the end of the current frame in the bitstream.
|
||||
* @return the position of the first byte of the next frame, or -1
|
||||
*/
|
||||
static int opus_find_frame_end(AVCodecParserContext *ctx, AVCodecContext *avctx,
|
||||
const uint8_t *buf, int buf_size, int *header_len)
|
||||
{
|
||||
OpusParserContext *s = ctx->priv_data;
|
||||
ParseContext *pc = &s->pc;
|
||||
int ret, start_found, i = 0, payload_len = 0;
|
||||
const uint8_t *payload;
|
||||
uint32_t state;
|
||||
uint16_t hdr;
|
||||
*header_len = 0;
|
||||
|
||||
if (!buf_size)
|
||||
return 0;
|
||||
|
||||
start_found = pc->frame_start_found;
|
||||
state = pc->state;
|
||||
payload = buf;
|
||||
|
||||
/* Check if we're using Opus in MPEG-TS framing */
|
||||
if (!s->ts_framing && buf_size > 2) {
|
||||
hdr = AV_RB16(buf);
|
||||
if ((hdr & OPUS_TS_MASK) == OPUS_TS_HEADER)
|
||||
s->ts_framing = 1;
|
||||
}
|
||||
|
||||
if (s->ts_framing && !start_found) {
|
||||
for (i = 0; i < buf_size-2; i++) {
|
||||
state = (state << 8) | payload[i];
|
||||
if ((state & OPUS_TS_MASK) == OPUS_TS_HEADER) {
|
||||
payload = parse_opus_ts_header(payload, &payload_len, buf_size - i);
|
||||
if (!payload) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error parsing Ogg TS header.\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
*header_len = payload - buf;
|
||||
start_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!s->ts_framing)
|
||||
payload_len = buf_size;
|
||||
|
||||
if (payload_len <= buf_size && (!s->ts_framing || start_found)) {
|
||||
ret = set_frame_duration(ctx, avctx, payload, payload_len);
|
||||
if (ret < 0) {
|
||||
pc->frame_start_found = 0;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->ts_framing) {
|
||||
if (start_found) {
|
||||
if (payload_len + *header_len <= buf_size) {
|
||||
pc->frame_start_found = 0;
|
||||
pc->state = -1;
|
||||
return payload_len + *header_len;
|
||||
}
|
||||
}
|
||||
|
||||
pc->frame_start_found = start_found;
|
||||
pc->state = state;
|
||||
return END_NOT_FOUND;
|
||||
}
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static int opus_parse(AVCodecParserContext *ctx, AVCodecContext *avctx,
|
||||
const uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
OpusParserContext *s = ctx->priv_data;
|
||||
ParseContext *pc = &s->pc;
|
||||
int next, header_len = 0;
|
||||
|
||||
avctx->sample_rate = 48000;
|
||||
|
||||
if (avctx->extradata && !s->extradata_parsed) {
|
||||
if (ff_opus_parse_extradata(avctx, &s->ctx) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error parsing Ogg extradata.\n");
|
||||
goto fail;
|
||||
}
|
||||
av_freep(&s->ctx.channel_maps);
|
||||
s->extradata_parsed = 1;
|
||||
}
|
||||
|
||||
if (ctx->flags & PARSER_FLAG_COMPLETE_FRAMES) {
|
||||
next = buf_size;
|
||||
|
||||
if (set_frame_duration(ctx, avctx, buf, buf_size) < 0)
|
||||
goto fail;
|
||||
} else {
|
||||
next = opus_find_frame_end(ctx, avctx, buf, buf_size, &header_len);
|
||||
|
||||
if (s->ts_framing && next != AVERROR_INVALIDDATA &&
|
||||
ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (next == AVERROR_INVALIDDATA){
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
*poutbuf = buf + header_len;
|
||||
*poutbuf_size = buf_size - header_len;
|
||||
return next;
|
||||
|
||||
fail:
|
||||
*poutbuf = NULL;
|
||||
*poutbuf_size = 0;
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
const AVCodecParser ff_opus_parser = {
|
||||
.codec_ids = { AV_CODEC_ID_OPUS },
|
||||
.priv_data_size = sizeof(OpusParserContext),
|
||||
.parser_parse = opus_parse,
|
||||
.parser_close = ff_parse_close
|
||||
};
|
||||
@@ -0,0 +1,930 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2008 CSIRO
|
||||
* Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
* Copyright (c) 2008-2009 Gregory Maxwell
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
* Copyright (c) 2017 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include "config_components.h"
|
||||
|
||||
#include "libavutil/mem.h"
|
||||
#include "mathops.h"
|
||||
#include "tab.h"
|
||||
#include "pvq.h"
|
||||
|
||||
#define ROUND_MUL16(a,b) ((MUL16(a, b) + 16384) >> 15)
|
||||
|
||||
#define CELT_PVQ_U(n, k) (ff_celt_pvq_u_row[FFMIN(n, k)][FFMAX(n, k)])
|
||||
#define CELT_PVQ_V(n, k) (CELT_PVQ_U(n, k) + CELT_PVQ_U(n, (k) + 1))
|
||||
|
||||
static inline int16_t celt_cos(int16_t x)
|
||||
{
|
||||
x = (MUL16(x, x) + 4096) >> 13;
|
||||
x = (32767-x) + ROUND_MUL16(x, (-7651 + ROUND_MUL16(x, (8277 + ROUND_MUL16(-626, x)))));
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
static inline int celt_log2tan(int isin, int icos)
|
||||
{
|
||||
int lc, ls;
|
||||
lc = opus_ilog(icos);
|
||||
ls = opus_ilog(isin);
|
||||
icos <<= 15 - lc;
|
||||
isin <<= 15 - ls;
|
||||
return (ls << 11) - (lc << 11) +
|
||||
ROUND_MUL16(isin, ROUND_MUL16(isin, -2597) + 7932) -
|
||||
ROUND_MUL16(icos, ROUND_MUL16(icos, -2597) + 7932);
|
||||
}
|
||||
|
||||
static inline int celt_bits2pulses(const uint8_t *cache, int bits)
|
||||
{
|
||||
// TODO: Find the size of cache and make it into an array in the parameters list
|
||||
int i, low = 0, high;
|
||||
|
||||
high = cache[0];
|
||||
bits--;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
int center = (low + high + 1) >> 1;
|
||||
if (cache[center] >= bits)
|
||||
high = center;
|
||||
else
|
||||
low = center;
|
||||
}
|
||||
|
||||
return (bits - (low == 0 ? -1 : cache[low]) <= cache[high] - bits) ? low : high;
|
||||
}
|
||||
|
||||
static inline int celt_pulses2bits(const uint8_t *cache, int pulses)
|
||||
{
|
||||
// TODO: Find the size of cache and make it into an array in the parameters list
|
||||
return (pulses == 0) ? 0 : cache[pulses] + 1;
|
||||
}
|
||||
|
||||
static inline void celt_normalize_residual(const int * restrict iy, float * restrict X,
|
||||
int N, float g)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < N; i++)
|
||||
X[i] = g * iy[i];
|
||||
}
|
||||
|
||||
static void celt_exp_rotation_impl(float *X, uint32_t len, uint32_t stride,
|
||||
float c, float s)
|
||||
{
|
||||
float *Xptr;
|
||||
int i;
|
||||
|
||||
Xptr = X;
|
||||
for (i = 0; i < len - stride; i++) {
|
||||
float x1 = Xptr[0];
|
||||
float x2 = Xptr[stride];
|
||||
Xptr[stride] = c * x2 + s * x1;
|
||||
*Xptr++ = c * x1 - s * x2;
|
||||
}
|
||||
|
||||
Xptr = &X[len - 2 * stride - 1];
|
||||
for (i = len - 2 * stride - 1; i >= 0; i--) {
|
||||
float x1 = Xptr[0];
|
||||
float x2 = Xptr[stride];
|
||||
Xptr[stride] = c * x2 + s * x1;
|
||||
*Xptr-- = c * x1 - s * x2;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void celt_exp_rotation(float *X, uint32_t len,
|
||||
uint32_t stride, uint32_t K,
|
||||
enum CeltSpread spread, const int encode)
|
||||
{
|
||||
uint32_t stride2 = 0;
|
||||
float c, s;
|
||||
float gain, theta;
|
||||
int i;
|
||||
|
||||
if (2*K >= len || spread == CELT_SPREAD_NONE)
|
||||
return;
|
||||
|
||||
gain = (float)len / (len + (20 - 5*spread) * K);
|
||||
theta = M_PI * gain * gain / 4;
|
||||
|
||||
c = cosf(theta);
|
||||
s = sinf(theta);
|
||||
|
||||
if (len >= stride << 3) {
|
||||
stride2 = 1;
|
||||
/* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding.
|
||||
It's basically incrementing long as (stride2+0.5)^2 < len/stride. */
|
||||
while ((stride2 * stride2 + stride2) * stride + (stride >> 2) < len)
|
||||
stride2++;
|
||||
}
|
||||
|
||||
len /= stride;
|
||||
for (i = 0; i < stride; i++) {
|
||||
if (encode) {
|
||||
celt_exp_rotation_impl(X + i * len, len, 1, c, -s);
|
||||
if (stride2)
|
||||
celt_exp_rotation_impl(X + i * len, len, stride2, s, -c);
|
||||
} else {
|
||||
if (stride2)
|
||||
celt_exp_rotation_impl(X + i * len, len, stride2, s, c);
|
||||
celt_exp_rotation_impl(X + i * len, len, 1, c, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t celt_extract_collapse_mask(const int *iy, uint32_t N, uint32_t B)
|
||||
{
|
||||
int i, j, N0 = N / B;
|
||||
uint32_t collapse_mask = 0;
|
||||
|
||||
if (B <= 1)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < B; i++)
|
||||
for (j = 0; j < N0; j++)
|
||||
collapse_mask |= (!!iy[i*N0+j]) << i;
|
||||
return collapse_mask;
|
||||
}
|
||||
|
||||
static inline void celt_stereo_merge(float *X, float *Y, float mid, int N)
|
||||
{
|
||||
int i;
|
||||
float xp = 0, side = 0;
|
||||
float E[2];
|
||||
float mid2;
|
||||
float gain[2];
|
||||
|
||||
/* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */
|
||||
for (i = 0; i < N; i++) {
|
||||
xp += X[i] * Y[i];
|
||||
side += Y[i] * Y[i];
|
||||
}
|
||||
|
||||
/* Compensating for the mid normalization */
|
||||
xp *= mid;
|
||||
mid2 = mid;
|
||||
E[0] = mid2 * mid2 + side - 2 * xp;
|
||||
E[1] = mid2 * mid2 + side + 2 * xp;
|
||||
if (E[0] < 6e-4f || E[1] < 6e-4f) {
|
||||
for (i = 0; i < N; i++)
|
||||
Y[i] = X[i];
|
||||
return;
|
||||
}
|
||||
|
||||
gain[0] = 1.0f / sqrtf(E[0]);
|
||||
gain[1] = 1.0f / sqrtf(E[1]);
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
float value[2];
|
||||
/* Apply mid scaling (side is already scaled) */
|
||||
value[0] = mid * X[i];
|
||||
value[1] = Y[i];
|
||||
X[i] = gain[0] * (value[0] - value[1]);
|
||||
Y[i] = gain[1] * (value[0] + value[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void celt_interleave_hadamard(float *tmp, float *X, int N0,
|
||||
int stride, int hadamard)
|
||||
{
|
||||
int i, j, N = N0*stride;
|
||||
const uint8_t *order = &ff_celt_hadamard_order[hadamard ? stride - 2 : 30];
|
||||
|
||||
for (i = 0; i < stride; i++)
|
||||
for (j = 0; j < N0; j++)
|
||||
tmp[j*stride+i] = X[order[i]*N0+j];
|
||||
|
||||
memcpy(X, tmp, N*sizeof(float));
|
||||
}
|
||||
|
||||
static void celt_deinterleave_hadamard(float *tmp, float *X, int N0,
|
||||
int stride, int hadamard)
|
||||
{
|
||||
int i, j, N = N0*stride;
|
||||
const uint8_t *order = &ff_celt_hadamard_order[hadamard ? stride - 2 : 30];
|
||||
|
||||
for (i = 0; i < stride; i++)
|
||||
for (j = 0; j < N0; j++)
|
||||
tmp[order[i]*N0+j] = X[j*stride+i];
|
||||
|
||||
memcpy(X, tmp, N*sizeof(float));
|
||||
}
|
||||
|
||||
static void celt_haar1(float *X, int N0, int stride)
|
||||
{
|
||||
int i, j;
|
||||
N0 >>= 1;
|
||||
for (i = 0; i < stride; i++) {
|
||||
for (j = 0; j < N0; j++) {
|
||||
float x0 = X[stride * (2 * j + 0) + i];
|
||||
float x1 = X[stride * (2 * j + 1) + i];
|
||||
X[stride * (2 * j + 0) + i] = (x0 + x1) * M_SQRT1_2;
|
||||
X[stride * (2 * j + 1) + i] = (x0 - x1) * M_SQRT1_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int celt_compute_qn(int N, int b, int offset, int pulse_cap,
|
||||
int stereo)
|
||||
{
|
||||
int qn, qb;
|
||||
int N2 = 2 * N - 1;
|
||||
if (stereo && N == 2)
|
||||
N2--;
|
||||
|
||||
/* The upper limit ensures that in a stereo split with itheta==16384, we'll
|
||||
* always have enough bits left over to code at least one pulse in the
|
||||
* side; otherwise it would collapse, since it doesn't get folded. */
|
||||
qb = FFMIN3(b - pulse_cap - (4 << 3), (b + N2 * offset) / N2, 8 << 3);
|
||||
qn = (qb < (1 << 3 >> 1)) ? 1 : ((ff_celt_qn_exp2[qb & 0x7] >> (14 - (qb >> 3))) + 1) >> 1 << 1;
|
||||
return qn;
|
||||
}
|
||||
|
||||
/* Convert the quantized vector to an index */
|
||||
static inline uint32_t celt_icwrsi(uint32_t N, uint32_t K, const int *y)
|
||||
{
|
||||
int i, idx = 0, sum = 0;
|
||||
for (i = N - 1; i >= 0; i--) {
|
||||
const uint32_t i_s = CELT_PVQ_U(N - i, sum + FFABS(y[i]) + 1);
|
||||
idx += CELT_PVQ_U(N - i, sum) + (y[i] < 0)*i_s;
|
||||
sum += FFABS(y[i]);
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
// this code was adapted from libopus
|
||||
static inline uint64_t celt_cwrsi(uint32_t N, uint32_t K, uint32_t i, int *y)
|
||||
{
|
||||
uint64_t norm = 0;
|
||||
uint32_t q, p;
|
||||
int s, val;
|
||||
int k0;
|
||||
|
||||
while (N > 2) {
|
||||
/*Lots of pulses case:*/
|
||||
if (K >= N) {
|
||||
const uint32_t *row = ff_celt_pvq_u_row[N];
|
||||
|
||||
/* Are the pulses in this dimension negative? */
|
||||
p = row[K + 1];
|
||||
s = -(i >= p);
|
||||
i -= p & s;
|
||||
|
||||
/*Count how many pulses were placed in this dimension.*/
|
||||
k0 = K;
|
||||
q = row[N];
|
||||
if (q > i) {
|
||||
K = N;
|
||||
do {
|
||||
p = ff_celt_pvq_u_row[--K][N];
|
||||
} while (p > i);
|
||||
} else
|
||||
for (p = row[K]; p > i; p = row[K])
|
||||
K--;
|
||||
|
||||
i -= p;
|
||||
val = (k0 - K + s) ^ s;
|
||||
norm += val * val;
|
||||
*y++ = val;
|
||||
} else { /*Lots of dimensions case:*/
|
||||
/*Are there any pulses in this dimension at all?*/
|
||||
p = ff_celt_pvq_u_row[K ][N];
|
||||
q = ff_celt_pvq_u_row[K + 1][N];
|
||||
|
||||
if (p <= i && i < q) {
|
||||
i -= p;
|
||||
*y++ = 0;
|
||||
} else {
|
||||
/*Are the pulses in this dimension negative?*/
|
||||
s = -(i >= q);
|
||||
i -= q & s;
|
||||
|
||||
/*Count how many pulses were placed in this dimension.*/
|
||||
k0 = K;
|
||||
do p = ff_celt_pvq_u_row[--K][N];
|
||||
while (p > i);
|
||||
|
||||
i -= p;
|
||||
val = (k0 - K + s) ^ s;
|
||||
norm += val * val;
|
||||
*y++ = val;
|
||||
}
|
||||
}
|
||||
N--;
|
||||
}
|
||||
|
||||
/* N == 2 */
|
||||
p = 2 * K + 1;
|
||||
s = -(i >= p);
|
||||
i -= p & s;
|
||||
k0 = K;
|
||||
K = (i + 1) / 2;
|
||||
|
||||
if (K)
|
||||
i -= 2 * K - 1;
|
||||
|
||||
val = (k0 - K + s) ^ s;
|
||||
norm += val * val;
|
||||
*y++ = val;
|
||||
|
||||
/* N==1 */
|
||||
s = -i;
|
||||
val = (K + s) ^ s;
|
||||
norm += val * val;
|
||||
*y = val;
|
||||
|
||||
return norm;
|
||||
}
|
||||
|
||||
static inline void celt_encode_pulses(OpusRangeCoder *rc, int *y, uint32_t N, uint32_t K)
|
||||
{
|
||||
ff_opus_rc_enc_uint(rc, celt_icwrsi(N, K, y), CELT_PVQ_V(N, K));
|
||||
}
|
||||
|
||||
static inline float celt_decode_pulses(OpusRangeCoder *rc, int *y, uint32_t N, uint32_t K)
|
||||
{
|
||||
const uint32_t idx = ff_opus_rc_dec_uint(rc, CELT_PVQ_V(N, K));
|
||||
return celt_cwrsi(N, K, idx, y);
|
||||
}
|
||||
|
||||
#if CONFIG_OPUS_ENCODER
|
||||
/*
|
||||
* Faster than libopus's search, operates entirely in the signed domain.
|
||||
* Slightly worse/better depending on N, K and the input vector.
|
||||
*/
|
||||
static float ppp_pvq_search_c(float *X, int *y, int K, int N)
|
||||
{
|
||||
int i, y_norm = 0;
|
||||
float res = 0.0f, xy_norm = 0.0f;
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
res += FFABS(X[i]);
|
||||
|
||||
res = K/(res + FLT_EPSILON);
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
y[i] = lrintf(res*X[i]);
|
||||
y_norm += y[i]*y[i];
|
||||
xy_norm += y[i]*X[i];
|
||||
K -= FFABS(y[i]);
|
||||
}
|
||||
|
||||
while (K) {
|
||||
int max_idx = 0, phase = FFSIGN(K);
|
||||
float max_num = 0.0f;
|
||||
float max_den = 1.0f;
|
||||
y_norm += 1.0f;
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
/* If the sum has been overshot and the best place has 0 pulses allocated
|
||||
* to it, attempting to decrease it further will actually increase the
|
||||
* sum. Prevent this by disregarding any 0 positions when decrementing. */
|
||||
const int ca = 1 ^ ((y[i] == 0) & (phase < 0));
|
||||
const int y_new = y_norm + 2*phase*FFABS(y[i]);
|
||||
float xy_new = xy_norm + 1*phase*FFABS(X[i]);
|
||||
xy_new = xy_new * xy_new;
|
||||
if (ca && (max_den*xy_new) > (y_new*max_num)) {
|
||||
max_den = y_new;
|
||||
max_num = xy_new;
|
||||
max_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
K -= phase;
|
||||
|
||||
phase *= FFSIGN(X[max_idx]);
|
||||
xy_norm += 1*phase*X[max_idx];
|
||||
y_norm += 2*phase*y[max_idx];
|
||||
y[max_idx] += phase;
|
||||
}
|
||||
|
||||
return (float)y_norm;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t celt_alg_quant(OpusRangeCoder *rc, float *X, uint32_t N, uint32_t K,
|
||||
enum CeltSpread spread, uint32_t blocks, float gain,
|
||||
CeltPVQ *pvq)
|
||||
{
|
||||
int *y = pvq->qcoeff;
|
||||
|
||||
celt_exp_rotation(X, N, blocks, K, spread, 1);
|
||||
gain /= sqrtf(pvq->pvq_search(X, y, K, N));
|
||||
celt_encode_pulses(rc, y, N, K);
|
||||
celt_normalize_residual(y, X, N, gain);
|
||||
celt_exp_rotation(X, N, blocks, K, spread, 0);
|
||||
return celt_extract_collapse_mask(y, N, blocks);
|
||||
}
|
||||
|
||||
/** Decode pulse vector and combine the result with the pitch vector to produce
|
||||
the final normalised signal in the current band. */
|
||||
static uint32_t celt_alg_unquant(OpusRangeCoder *rc, float *X, uint32_t N, uint32_t K,
|
||||
enum CeltSpread spread, uint32_t blocks, float gain,
|
||||
CeltPVQ *pvq)
|
||||
{
|
||||
int *y = pvq->qcoeff;
|
||||
|
||||
gain /= sqrtf(celt_decode_pulses(rc, y, N, K));
|
||||
celt_normalize_residual(y, X, N, gain);
|
||||
celt_exp_rotation(X, N, blocks, K, spread, 0);
|
||||
return celt_extract_collapse_mask(y, N, blocks);
|
||||
}
|
||||
|
||||
static int celt_calc_theta(const float *X, const float *Y, int coupling, int N)
|
||||
{
|
||||
int i;
|
||||
float e[2] = { 0.0f, 0.0f };
|
||||
if (coupling) { /* Coupling case */
|
||||
for (i = 0; i < N; i++) {
|
||||
e[0] += (X[i] + Y[i])*(X[i] + Y[i]);
|
||||
e[1] += (X[i] - Y[i])*(X[i] - Y[i]);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < N; i++) {
|
||||
e[0] += X[i]*X[i];
|
||||
e[1] += Y[i]*Y[i];
|
||||
}
|
||||
}
|
||||
return lrintf(32768.0f*atan2f(sqrtf(e[1]), sqrtf(e[0]))/M_PI);
|
||||
}
|
||||
|
||||
static void celt_stereo_is_decouple(float *X, float *Y, float e_l, float e_r, int N)
|
||||
{
|
||||
int i;
|
||||
const float energy_n = 1.0f/(sqrtf(e_l*e_l + e_r*e_r) + FLT_EPSILON);
|
||||
e_l *= energy_n;
|
||||
e_r *= energy_n;
|
||||
for (i = 0; i < N; i++)
|
||||
X[i] = e_l*X[i] + e_r*Y[i];
|
||||
}
|
||||
|
||||
static void celt_stereo_ms_decouple(float *X, float *Y, int N)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < N; i++) {
|
||||
const float Xret = X[i];
|
||||
X[i] = (X[i] + Y[i])*M_SQRT1_2;
|
||||
Y[i] = (Y[i] - Xret)*M_SQRT1_2;
|
||||
}
|
||||
}
|
||||
|
||||
static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f,
|
||||
OpusRangeCoder *rc,
|
||||
const int band, float *X,
|
||||
float *Y, int N, int b,
|
||||
uint32_t blocks, float *lowband,
|
||||
int duration, float *lowband_out,
|
||||
int level, float gain,
|
||||
float *lowband_scratch,
|
||||
int fill, int quant)
|
||||
{
|
||||
int i;
|
||||
const uint8_t *cache;
|
||||
int stereo = !!Y, split = stereo;
|
||||
int imid = 0, iside = 0;
|
||||
uint32_t N0 = N;
|
||||
int N_B = N / blocks;
|
||||
int N_B0 = N_B;
|
||||
int B0 = blocks;
|
||||
int time_divide = 0;
|
||||
int recombine = 0;
|
||||
int inv = 0;
|
||||
float mid = 0, side = 0;
|
||||
int longblocks = (B0 == 1);
|
||||
uint32_t cm = 0;
|
||||
|
||||
if (N == 1) {
|
||||
float *x = X;
|
||||
for (i = 0; i <= stereo; i++) {
|
||||
int sign = 0;
|
||||
if (f->remaining2 >= 1 << 3) {
|
||||
if (quant) {
|
||||
sign = x[0] < 0;
|
||||
ff_opus_rc_put_raw(rc, sign, 1);
|
||||
} else {
|
||||
sign = ff_opus_rc_get_raw(rc, 1);
|
||||
}
|
||||
f->remaining2 -= 1 << 3;
|
||||
}
|
||||
x[0] = 1.0f - 2.0f*sign;
|
||||
x = Y;
|
||||
}
|
||||
if (lowband_out)
|
||||
lowband_out[0] = X[0];
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!stereo && level == 0) {
|
||||
int tf_change = f->tf_change[band];
|
||||
int k;
|
||||
if (tf_change > 0)
|
||||
recombine = tf_change;
|
||||
/* Band recombining to increase frequency resolution */
|
||||
|
||||
if (lowband &&
|
||||
(recombine || ((N_B & 1) == 0 && tf_change < 0) || B0 > 1)) {
|
||||
for (i = 0; i < N; i++)
|
||||
lowband_scratch[i] = lowband[i];
|
||||
lowband = lowband_scratch;
|
||||
}
|
||||
|
||||
for (k = 0; k < recombine; k++) {
|
||||
if (quant || lowband)
|
||||
celt_haar1(quant ? X : lowband, N >> k, 1 << k);
|
||||
fill = ff_celt_bit_interleave[fill & 0xF] | ff_celt_bit_interleave[fill >> 4] << 2;
|
||||
}
|
||||
blocks >>= recombine;
|
||||
N_B <<= recombine;
|
||||
|
||||
/* Increasing the time resolution */
|
||||
while ((N_B & 1) == 0 && tf_change < 0) {
|
||||
if (quant || lowband)
|
||||
celt_haar1(quant ? X : lowband, N_B, blocks);
|
||||
fill |= fill << blocks;
|
||||
blocks <<= 1;
|
||||
N_B >>= 1;
|
||||
time_divide++;
|
||||
tf_change++;
|
||||
}
|
||||
B0 = blocks;
|
||||
N_B0 = N_B;
|
||||
|
||||
/* Reorganize the samples in time order instead of frequency order */
|
||||
if (B0 > 1 && (quant || lowband))
|
||||
celt_deinterleave_hadamard(pvq->hadamard_tmp, quant ? X : lowband,
|
||||
N_B >> recombine, B0 << recombine,
|
||||
longblocks);
|
||||
}
|
||||
|
||||
/* If we need 1.5 more bit than we can produce, split the band in two. */
|
||||
cache = ff_celt_cache_bits +
|
||||
ff_celt_cache_index[(duration + 1) * CELT_MAX_BANDS + band];
|
||||
if (!stereo && duration >= 0 && b > cache[cache[0]] + 12 && N > 2) {
|
||||
N >>= 1;
|
||||
Y = X + N;
|
||||
split = 1;
|
||||
duration -= 1;
|
||||
if (blocks == 1)
|
||||
fill = (fill & 1) | (fill << 1);
|
||||
blocks = (blocks + 1) >> 1;
|
||||
}
|
||||
|
||||
if (split) {
|
||||
int qn;
|
||||
int itheta = quant ? celt_calc_theta(X, Y, stereo, N) : 0;
|
||||
int mbits, sbits, delta;
|
||||
int qalloc;
|
||||
int pulse_cap;
|
||||
int offset;
|
||||
int orig_fill;
|
||||
int tell;
|
||||
|
||||
/* Decide on the resolution to give to the split parameter theta */
|
||||
pulse_cap = ff_celt_log_freq_range[band] + duration * 8;
|
||||
offset = (pulse_cap >> 1) - (stereo && N == 2 ? CELT_QTHETA_OFFSET_TWOPHASE :
|
||||
CELT_QTHETA_OFFSET);
|
||||
qn = (stereo && band >= f->intensity_stereo) ? 1 :
|
||||
celt_compute_qn(N, b, offset, pulse_cap, stereo);
|
||||
tell = opus_rc_tell_frac(rc);
|
||||
if (qn != 1) {
|
||||
if (quant)
|
||||
itheta = (itheta*qn + 8192) >> 14;
|
||||
/* Entropy coding of the angle. We use a uniform pdf for the
|
||||
* time split, a step for stereo, and a triangular one for the rest. */
|
||||
if (quant) {
|
||||
if (stereo && N > 2)
|
||||
ff_opus_rc_enc_uint_step(rc, itheta, qn / 2);
|
||||
else if (stereo || B0 > 1)
|
||||
ff_opus_rc_enc_uint(rc, itheta, qn + 1);
|
||||
else
|
||||
ff_opus_rc_enc_uint_tri(rc, itheta, qn);
|
||||
itheta = itheta * 16384 / qn;
|
||||
if (stereo) {
|
||||
if (itheta == 0)
|
||||
celt_stereo_is_decouple(X, Y, f->block[0].lin_energy[band],
|
||||
f->block[1].lin_energy[band], N);
|
||||
else
|
||||
celt_stereo_ms_decouple(X, Y, N);
|
||||
}
|
||||
} else {
|
||||
if (stereo && N > 2)
|
||||
itheta = ff_opus_rc_dec_uint_step(rc, qn / 2);
|
||||
else if (stereo || B0 > 1)
|
||||
itheta = ff_opus_rc_dec_uint(rc, qn+1);
|
||||
else
|
||||
itheta = ff_opus_rc_dec_uint_tri(rc, qn);
|
||||
itheta = itheta * 16384 / qn;
|
||||
}
|
||||
} else if (stereo) {
|
||||
if (quant) {
|
||||
inv = f->apply_phase_inv ? itheta > 8192 : 0;
|
||||
if (inv) {
|
||||
for (i = 0; i < N; i++)
|
||||
Y[i] *= -1;
|
||||
}
|
||||
celt_stereo_is_decouple(X, Y, f->block[0].lin_energy[band],
|
||||
f->block[1].lin_energy[band], N);
|
||||
|
||||
if (b > 2 << 3 && f->remaining2 > 2 << 3) {
|
||||
ff_opus_rc_enc_log(rc, inv, 2);
|
||||
} else {
|
||||
inv = 0;
|
||||
}
|
||||
} else {
|
||||
inv = (b > 2 << 3 && f->remaining2 > 2 << 3) ? ff_opus_rc_dec_log(rc, 2) : 0;
|
||||
inv = f->apply_phase_inv ? inv : 0;
|
||||
}
|
||||
itheta = 0;
|
||||
}
|
||||
qalloc = opus_rc_tell_frac(rc) - tell;
|
||||
b -= qalloc;
|
||||
|
||||
orig_fill = fill;
|
||||
if (itheta == 0) {
|
||||
imid = 32767;
|
||||
iside = 0;
|
||||
fill = av_zero_extend(fill, blocks);
|
||||
delta = -16384;
|
||||
} else if (itheta == 16384) {
|
||||
imid = 0;
|
||||
iside = 32767;
|
||||
fill &= ((1 << blocks) - 1) << blocks;
|
||||
delta = 16384;
|
||||
} else {
|
||||
imid = celt_cos(itheta);
|
||||
iside = celt_cos(16384-itheta);
|
||||
/* This is the mid vs side allocation that minimizes squared error
|
||||
in that band. */
|
||||
delta = ROUND_MUL16((N - 1) << 7, celt_log2tan(iside, imid));
|
||||
}
|
||||
|
||||
mid = imid / 32768.0f;
|
||||
side = iside / 32768.0f;
|
||||
|
||||
/* This is a special case for N=2 that only works for stereo and takes
|
||||
advantage of the fact that mid and side are orthogonal to encode
|
||||
the side with just one bit. */
|
||||
if (N == 2 && stereo) {
|
||||
int c;
|
||||
int sign = 0;
|
||||
float tmp;
|
||||
float *x2, *y2;
|
||||
mbits = b;
|
||||
/* Only need one bit for the side */
|
||||
sbits = (itheta != 0 && itheta != 16384) ? 1 << 3 : 0;
|
||||
mbits -= sbits;
|
||||
c = (itheta > 8192);
|
||||
f->remaining2 -= qalloc+sbits;
|
||||
|
||||
x2 = c ? Y : X;
|
||||
y2 = c ? X : Y;
|
||||
if (sbits) {
|
||||
if (quant) {
|
||||
sign = x2[0]*y2[1] - x2[1]*y2[0] < 0;
|
||||
ff_opus_rc_put_raw(rc, sign, 1);
|
||||
} else {
|
||||
sign = ff_opus_rc_get_raw(rc, 1);
|
||||
}
|
||||
}
|
||||
sign = 1 - 2 * sign;
|
||||
/* We use orig_fill here because we want to fold the side, but if
|
||||
itheta==16384, we'll have cleared the low bits of fill. */
|
||||
cm = pvq->quant_band(pvq, f, rc, band, x2, NULL, N, mbits, blocks, lowband, duration,
|
||||
lowband_out, level, gain, lowband_scratch, orig_fill);
|
||||
/* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
|
||||
and there's no need to worry about mixing with the other channel. */
|
||||
y2[0] = -sign * x2[1];
|
||||
y2[1] = sign * x2[0];
|
||||
X[0] *= mid;
|
||||
X[1] *= mid;
|
||||
Y[0] *= side;
|
||||
Y[1] *= side;
|
||||
tmp = X[0];
|
||||
X[0] = tmp - Y[0];
|
||||
Y[0] = tmp + Y[0];
|
||||
tmp = X[1];
|
||||
X[1] = tmp - Y[1];
|
||||
Y[1] = tmp + Y[1];
|
||||
} else {
|
||||
/* "Normal" split code */
|
||||
float *next_lowband2 = NULL;
|
||||
float *next_lowband_out1 = NULL;
|
||||
int next_level = 0;
|
||||
int rebalance;
|
||||
uint32_t cmt;
|
||||
|
||||
/* Give more bits to low-energy MDCTs than they would
|
||||
* otherwise deserve */
|
||||
if (B0 > 1 && !stereo && (itheta & 0x3fff)) {
|
||||
if (itheta > 8192)
|
||||
/* Rough approximation for pre-echo masking */
|
||||
delta -= delta >> (4 - duration);
|
||||
else
|
||||
/* Corresponds to a forward-masking slope of
|
||||
* 1.5 dB per 10 ms */
|
||||
delta = FFMIN(0, delta + (N << 3 >> (5 - duration)));
|
||||
}
|
||||
mbits = av_clip((b - delta) / 2, 0, b);
|
||||
sbits = b - mbits;
|
||||
f->remaining2 -= qalloc;
|
||||
|
||||
if (lowband && !stereo)
|
||||
next_lowband2 = lowband + N; /* >32-bit split case */
|
||||
|
||||
/* Only stereo needs to pass on lowband_out.
|
||||
* Otherwise, it's handled at the end */
|
||||
if (stereo)
|
||||
next_lowband_out1 = lowband_out;
|
||||
else
|
||||
next_level = level + 1;
|
||||
|
||||
rebalance = f->remaining2;
|
||||
if (mbits >= sbits) {
|
||||
/* In stereo mode, we do not apply a scaling to the mid
|
||||
* because we need the normalized mid for folding later */
|
||||
cm = pvq->quant_band(pvq, f, rc, band, X, NULL, N, mbits, blocks,
|
||||
lowband, duration, next_lowband_out1, next_level,
|
||||
stereo ? 1.0f : (gain * mid), lowband_scratch, fill);
|
||||
rebalance = mbits - (rebalance - f->remaining2);
|
||||
if (rebalance > 3 << 3 && itheta != 0)
|
||||
sbits += rebalance - (3 << 3);
|
||||
|
||||
/* For a stereo split, the high bits of fill are always zero,
|
||||
* so no folding will be done to the side. */
|
||||
cmt = pvq->quant_band(pvq, f, rc, band, Y, NULL, N, sbits, blocks,
|
||||
next_lowband2, duration, NULL, next_level,
|
||||
gain * side, NULL, fill >> blocks);
|
||||
cm |= cmt << ((B0 >> 1) & (stereo - 1));
|
||||
} else {
|
||||
/* For a stereo split, the high bits of fill are always zero,
|
||||
* so no folding will be done to the side. */
|
||||
cm = pvq->quant_band(pvq, f, rc, band, Y, NULL, N, sbits, blocks,
|
||||
next_lowband2, duration, NULL, next_level,
|
||||
gain * side, NULL, fill >> blocks);
|
||||
cm <<= ((B0 >> 1) & (stereo - 1));
|
||||
rebalance = sbits - (rebalance - f->remaining2);
|
||||
if (rebalance > 3 << 3 && itheta != 16384)
|
||||
mbits += rebalance - (3 << 3);
|
||||
|
||||
/* In stereo mode, we do not apply a scaling to the mid because
|
||||
* we need the normalized mid for folding later */
|
||||
cm |= pvq->quant_band(pvq, f, rc, band, X, NULL, N, mbits, blocks,
|
||||
lowband, duration, next_lowband_out1, next_level,
|
||||
stereo ? 1.0f : (gain * mid), lowband_scratch, fill);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* This is the basic no-split case */
|
||||
uint32_t q = celt_bits2pulses(cache, b);
|
||||
uint32_t curr_bits = celt_pulses2bits(cache, q);
|
||||
f->remaining2 -= curr_bits;
|
||||
|
||||
/* Ensures we can never bust the budget */
|
||||
while (f->remaining2 < 0 && q > 0) {
|
||||
f->remaining2 += curr_bits;
|
||||
curr_bits = celt_pulses2bits(cache, --q);
|
||||
f->remaining2 -= curr_bits;
|
||||
}
|
||||
|
||||
if (q != 0) {
|
||||
/* Finally do the actual (de)quantization */
|
||||
if (quant) {
|
||||
cm = celt_alg_quant(rc, X, N, (q < 8) ? q : (8 + (q & 7)) << ((q >> 3) - 1),
|
||||
f->spread, blocks, gain, pvq);
|
||||
} else {
|
||||
cm = celt_alg_unquant(rc, X, N, (q < 8) ? q : (8 + (q & 7)) << ((q >> 3) - 1),
|
||||
f->spread, blocks, gain, pvq);
|
||||
}
|
||||
} else {
|
||||
/* If there's no pulse, fill the band anyway */
|
||||
uint32_t cm_mask = (1 << blocks) - 1;
|
||||
fill &= cm_mask;
|
||||
if (fill) {
|
||||
if (!lowband) {
|
||||
/* Noise */
|
||||
for (i = 0; i < N; i++)
|
||||
X[i] = (((int32_t)celt_rng(f)) >> 20);
|
||||
cm = cm_mask;
|
||||
} else {
|
||||
/* Folded spectrum */
|
||||
for (i = 0; i < N; i++) {
|
||||
/* About 48 dB below the "normal" folding level */
|
||||
X[i] = lowband[i] + (((celt_rng(f)) & 0x8000) ? 1.0f / 256 : -1.0f / 256);
|
||||
}
|
||||
cm = fill;
|
||||
}
|
||||
celt_renormalize_vector(X, N, gain);
|
||||
} else {
|
||||
memset(X, 0, N*sizeof(float));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This code is used by the decoder and by the resynthesis-enabled encoder */
|
||||
if (stereo) {
|
||||
if (N > 2)
|
||||
celt_stereo_merge(X, Y, mid, N);
|
||||
if (inv) {
|
||||
for (i = 0; i < N; i++)
|
||||
Y[i] *= -1;
|
||||
}
|
||||
} else if (level == 0) {
|
||||
int k;
|
||||
|
||||
/* Undo the sample reorganization going from time order to frequency order */
|
||||
if (B0 > 1)
|
||||
celt_interleave_hadamard(pvq->hadamard_tmp, X, N_B >> recombine,
|
||||
B0 << recombine, longblocks);
|
||||
|
||||
/* Undo time-freq changes that we did earlier */
|
||||
N_B = N_B0;
|
||||
blocks = B0;
|
||||
for (k = 0; k < time_divide; k++) {
|
||||
blocks >>= 1;
|
||||
N_B <<= 1;
|
||||
cm |= cm >> blocks;
|
||||
celt_haar1(X, N_B, blocks);
|
||||
}
|
||||
|
||||
for (k = 0; k < recombine; k++) {
|
||||
cm = ff_celt_bit_deinterleave[cm];
|
||||
celt_haar1(X, N0>>k, 1<<k);
|
||||
}
|
||||
blocks <<= recombine;
|
||||
|
||||
/* Scale output for later folding */
|
||||
if (lowband_out) {
|
||||
float n = sqrtf(N0);
|
||||
for (i = 0; i < N0; i++)
|
||||
lowband_out[i] = n * X[i];
|
||||
}
|
||||
cm = av_zero_extend(cm, blocks);
|
||||
}
|
||||
|
||||
return cm;
|
||||
}
|
||||
|
||||
static QUANT_FN(pvq_decode_band)
|
||||
{
|
||||
#if CONFIG_OPUS_DECODER
|
||||
return quant_band_template(pvq, f, rc, band, X, Y, N, b, blocks, lowband, duration,
|
||||
lowband_out, level, gain, lowband_scratch, fill, 0);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static QUANT_FN(pvq_encode_band)
|
||||
{
|
||||
#if CONFIG_OPUS_ENCODER
|
||||
return quant_band_template(pvq, f, rc, band, X, Y, N, b, blocks, lowband, duration,
|
||||
lowband_out, level, gain, lowband_scratch, fill, 1);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int av_cold ff_celt_pvq_init(CeltPVQ **pvq, int encode)
|
||||
{
|
||||
CeltPVQ *s = av_malloc(sizeof(CeltPVQ));
|
||||
if (!s)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
s->quant_band = encode ? pvq_encode_band : pvq_decode_band;
|
||||
|
||||
#if CONFIG_OPUS_ENCODER
|
||||
s->pvq_search = ppp_pvq_search_c;
|
||||
#if ARCH_X86
|
||||
ff_celt_pvq_init_x86(s);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
*pvq = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void av_cold ff_celt_pvq_uninit(CeltPVQ **pvq)
|
||||
{
|
||||
av_freep(pvq);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
* Copyright (c) 2016 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_PVQ_H
|
||||
#define AVCODEC_OPUS_PVQ_H
|
||||
|
||||
#include "libavutil/mem_internal.h"
|
||||
|
||||
#include "celt.h"
|
||||
|
||||
#define QUANT_FN(name) uint32_t (name)(struct CeltPVQ *pvq, CeltFrame *f, \
|
||||
OpusRangeCoder *rc, const int band, float *X, \
|
||||
float *Y, int N, int b, uint32_t blocks, \
|
||||
float *lowband, int duration, \
|
||||
float *lowband_out, int level, float gain, \
|
||||
float *lowband_scratch, int fill)
|
||||
|
||||
typedef struct CeltPVQ {
|
||||
DECLARE_ALIGNED(32, int, qcoeff )[256];
|
||||
DECLARE_ALIGNED(32, float, hadamard_tmp)[256];
|
||||
|
||||
float (*pvq_search)(float *X, int *y, int K, int N);
|
||||
QUANT_FN(*quant_band);
|
||||
} CeltPVQ;
|
||||
|
||||
void ff_celt_pvq_init_x86(struct CeltPVQ *s);
|
||||
|
||||
int ff_celt_pvq_init(struct CeltPVQ **pvq, int encode);
|
||||
void ff_celt_pvq_uninit(struct CeltPVQ **pvq);
|
||||
|
||||
#endif /* AVCODEC_OPUS_PVQ_H */
|
||||
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
* Copyright (c) 2017 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "rc.h"
|
||||
|
||||
#define OPUS_RC_BITS 32
|
||||
#define OPUS_RC_SYM 8
|
||||
#define OPUS_RC_CEIL ((1 << OPUS_RC_SYM) - 1)
|
||||
#define OPUS_RC_TOP (1u << 31)
|
||||
#define OPUS_RC_BOT (OPUS_RC_TOP >> OPUS_RC_SYM)
|
||||
#define OPUS_RC_SHIFT (OPUS_RC_BITS - OPUS_RC_SYM - 1)
|
||||
|
||||
static av_always_inline void opus_rc_enc_carryout(OpusRangeCoder *rc, int cbuf)
|
||||
{
|
||||
const int cb = cbuf >> OPUS_RC_SYM, mb = (OPUS_RC_CEIL + cb) & OPUS_RC_CEIL;
|
||||
if (cbuf == OPUS_RC_CEIL) {
|
||||
rc->ext++;
|
||||
return;
|
||||
}
|
||||
rc->rng_cur[0] = rc->rem + cb;
|
||||
rc->rng_cur += (rc->rem >= 0);
|
||||
for (; rc->ext > 0; rc->ext--)
|
||||
*rc->rng_cur++ = mb;
|
||||
av_assert0(rc->rng_cur < rc->rb.position);
|
||||
rc->rem = cbuf & OPUS_RC_CEIL; /* Propagate */
|
||||
}
|
||||
|
||||
static av_always_inline void opus_rc_dec_normalize(OpusRangeCoder *rc)
|
||||
{
|
||||
while (rc->range <= OPUS_RC_BOT) {
|
||||
rc->value = ((rc->value << OPUS_RC_SYM) | (get_bits(&rc->gb, OPUS_RC_SYM) ^ OPUS_RC_CEIL)) & (OPUS_RC_TOP - 1);
|
||||
rc->range <<= OPUS_RC_SYM;
|
||||
rc->total_bits += OPUS_RC_SYM;
|
||||
}
|
||||
}
|
||||
|
||||
static av_always_inline void opus_rc_enc_normalize(OpusRangeCoder *rc)
|
||||
{
|
||||
while (rc->range <= OPUS_RC_BOT) {
|
||||
opus_rc_enc_carryout(rc, rc->value >> OPUS_RC_SHIFT);
|
||||
rc->value = (rc->value << OPUS_RC_SYM) & (OPUS_RC_TOP - 1);
|
||||
rc->range <<= OPUS_RC_SYM;
|
||||
rc->total_bits += OPUS_RC_SYM;
|
||||
}
|
||||
}
|
||||
|
||||
static av_always_inline void opus_rc_dec_update(OpusRangeCoder *rc, uint32_t scale,
|
||||
uint32_t low, uint32_t high,
|
||||
uint32_t total)
|
||||
{
|
||||
rc->value -= scale * (total - high);
|
||||
rc->range = low ? scale * (high - low)
|
||||
: rc->range - scale * (total - high);
|
||||
opus_rc_dec_normalize(rc);
|
||||
}
|
||||
|
||||
/* Main encoding function, this needs to go fast */
|
||||
static av_always_inline void opus_rc_enc_update(OpusRangeCoder *rc, uint32_t b, uint32_t p,
|
||||
uint32_t p_tot, const int ptwo)
|
||||
{
|
||||
uint32_t rscaled, cnd = !!b;
|
||||
if (ptwo) /* Whole function is inlined so hopefully branch is optimized out */
|
||||
rscaled = rc->range >> ff_log2(p_tot);
|
||||
else
|
||||
rscaled = rc->range/p_tot;
|
||||
rc->value += cnd*(rc->range - rscaled*(p_tot - b));
|
||||
rc->range = (!cnd)*(rc->range - rscaled*(p_tot - p)) + cnd*rscaled*(p - b);
|
||||
opus_rc_enc_normalize(rc);
|
||||
}
|
||||
|
||||
uint32_t ff_opus_rc_dec_cdf(OpusRangeCoder *rc, const uint16_t *cdf)
|
||||
{
|
||||
unsigned int k, scale, total, symbol, low, high;
|
||||
|
||||
total = *cdf++;
|
||||
|
||||
scale = rc->range / total;
|
||||
symbol = rc->value / scale + 1;
|
||||
symbol = total - FFMIN(symbol, total);
|
||||
|
||||
for (k = 0; cdf[k] <= symbol; k++);
|
||||
high = cdf[k];
|
||||
low = k ? cdf[k-1] : 0;
|
||||
|
||||
opus_rc_dec_update(rc, scale, low, high, total);
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
void ff_opus_rc_enc_cdf(OpusRangeCoder *rc, int val, const uint16_t *cdf)
|
||||
{
|
||||
opus_rc_enc_update(rc, (!!val)*cdf[val], cdf[val + 1], cdf[0], 1);
|
||||
}
|
||||
|
||||
uint32_t ff_opus_rc_dec_log(OpusRangeCoder *rc, uint32_t bits)
|
||||
{
|
||||
uint32_t k, scale;
|
||||
scale = rc->range >> bits; // in this case, scale = symbol
|
||||
|
||||
if (rc->value >= scale) {
|
||||
rc->value -= scale;
|
||||
rc->range -= scale;
|
||||
k = 0;
|
||||
} else {
|
||||
rc->range = scale;
|
||||
k = 1;
|
||||
}
|
||||
opus_rc_dec_normalize(rc);
|
||||
return k;
|
||||
}
|
||||
|
||||
void ff_opus_rc_enc_log(OpusRangeCoder *rc, int val, uint32_t bits)
|
||||
{
|
||||
bits = (1 << bits) - 1;
|
||||
opus_rc_enc_update(rc, (!!val)*bits, bits + !!val, bits + 1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* CELT: read 1-25 raw bits at the end of the frame, backwards byte-wise
|
||||
*/
|
||||
uint32_t ff_opus_rc_get_raw(OpusRangeCoder *rc, uint32_t count)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
|
||||
while (rc->rb.bytes && rc->rb.cachelen < count) {
|
||||
rc->rb.cacheval |= *--rc->rb.position << rc->rb.cachelen;
|
||||
rc->rb.cachelen += 8;
|
||||
rc->rb.bytes--;
|
||||
}
|
||||
|
||||
value = av_zero_extend(rc->rb.cacheval, count);
|
||||
rc->rb.cacheval >>= count;
|
||||
rc->rb.cachelen -= count;
|
||||
rc->total_bits += count;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* CELT: write 0 - 31 bits to the rawbits buffer
|
||||
*/
|
||||
void ff_opus_rc_put_raw(OpusRangeCoder *rc, uint32_t val, uint32_t count)
|
||||
{
|
||||
const int to_write = FFMIN(32 - rc->rb.cachelen, count);
|
||||
|
||||
rc->total_bits += count;
|
||||
rc->rb.cacheval |= av_zero_extend(val, to_write) << rc->rb.cachelen;
|
||||
rc->rb.cachelen = (rc->rb.cachelen + to_write) % 32;
|
||||
|
||||
if (!rc->rb.cachelen && count) {
|
||||
AV_WB32((uint8_t *)rc->rb.position, rc->rb.cacheval);
|
||||
rc->rb.bytes += 4;
|
||||
rc->rb.position -= 4;
|
||||
rc->rb.cachelen = count - to_write;
|
||||
rc->rb.cacheval = av_zero_extend(val >> to_write, rc->rb.cachelen);
|
||||
av_assert0(rc->rng_cur < rc->rb.position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CELT: read a uniform distribution
|
||||
*/
|
||||
uint32_t ff_opus_rc_dec_uint(OpusRangeCoder *rc, uint32_t size)
|
||||
{
|
||||
uint32_t bits, k, scale, total;
|
||||
|
||||
bits = opus_ilog(size - 1);
|
||||
total = (bits > 8) ? ((size - 1) >> (bits - 8)) + 1 : size;
|
||||
|
||||
scale = rc->range / total;
|
||||
k = rc->value / scale + 1;
|
||||
k = total - FFMIN(k, total);
|
||||
opus_rc_dec_update(rc, scale, k, k + 1, total);
|
||||
|
||||
if (bits > 8) {
|
||||
k = k << (bits - 8) | ff_opus_rc_get_raw(rc, bits - 8);
|
||||
return FFMIN(k, size - 1);
|
||||
} else
|
||||
return k;
|
||||
}
|
||||
|
||||
/**
|
||||
* CELT: write a uniformly distributed integer
|
||||
*/
|
||||
void ff_opus_rc_enc_uint(OpusRangeCoder *rc, uint32_t val, uint32_t size)
|
||||
{
|
||||
const int ps = FFMAX(opus_ilog(size - 1) - 8, 0);
|
||||
opus_rc_enc_update(rc, val >> ps, (val >> ps) + 1, ((size - 1) >> ps) + 1, 0);
|
||||
ff_opus_rc_put_raw(rc, val, ps);
|
||||
}
|
||||
|
||||
uint32_t ff_opus_rc_dec_uint_step(OpusRangeCoder *rc, int k0)
|
||||
{
|
||||
/* Use a probability of 3 up to itheta=8192 and then use 1 after */
|
||||
uint32_t k, scale, symbol, total = (k0+1)*3 + k0;
|
||||
scale = rc->range / total;
|
||||
symbol = rc->value / scale + 1;
|
||||
symbol = total - FFMIN(symbol, total);
|
||||
|
||||
k = (symbol < (k0+1)*3) ? symbol/3 : symbol - (k0+1)*2;
|
||||
|
||||
opus_rc_dec_update(rc, scale, (k <= k0) ? 3*(k+0) : (k-1-k0) + 3*(k0+1),
|
||||
(k <= k0) ? 3*(k+1) : (k-0-k0) + 3*(k0+1), total);
|
||||
return k;
|
||||
}
|
||||
|
||||
void ff_opus_rc_enc_uint_step(OpusRangeCoder *rc, uint32_t val, int k0)
|
||||
{
|
||||
const uint32_t a = val <= k0, b = 2*a + 1;
|
||||
k0 = (k0 + 1) << 1;
|
||||
val = b*(val + k0) - 3*a*k0;
|
||||
opus_rc_enc_update(rc, val, val + b, (k0 << 1) - 1, 0);
|
||||
}
|
||||
|
||||
uint32_t ff_opus_rc_dec_uint_tri(OpusRangeCoder *rc, int qn)
|
||||
{
|
||||
uint32_t k, scale, symbol, total, low, center;
|
||||
|
||||
total = ((qn>>1) + 1) * ((qn>>1) + 1);
|
||||
scale = rc->range / total;
|
||||
center = rc->value / scale + 1;
|
||||
center = total - FFMIN(center, total);
|
||||
|
||||
if (center < total >> 1) {
|
||||
k = (ff_sqrt(8 * center + 1) - 1) >> 1;
|
||||
low = k * (k + 1) >> 1;
|
||||
symbol = k + 1;
|
||||
} else {
|
||||
k = (2*(qn + 1) - ff_sqrt(8*(total - center - 1) + 1)) >> 1;
|
||||
low = total - ((qn + 1 - k) * (qn + 2 - k) >> 1);
|
||||
symbol = qn + 1 - k;
|
||||
}
|
||||
|
||||
opus_rc_dec_update(rc, scale, low, low + symbol, total);
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
void ff_opus_rc_enc_uint_tri(OpusRangeCoder *rc, uint32_t k, int qn)
|
||||
{
|
||||
uint32_t symbol, low, total;
|
||||
|
||||
total = ((qn>>1) + 1) * ((qn>>1) + 1);
|
||||
|
||||
if (k <= qn >> 1) {
|
||||
low = k * (k + 1) >> 1;
|
||||
symbol = k + 1;
|
||||
} else {
|
||||
low = total - ((qn + 1 - k) * (qn + 2 - k) >> 1);
|
||||
symbol = qn + 1 - k;
|
||||
}
|
||||
|
||||
opus_rc_enc_update(rc, low, low + symbol, total, 0);
|
||||
}
|
||||
|
||||
int ff_opus_rc_dec_laplace(OpusRangeCoder *rc, uint32_t symbol, int decay)
|
||||
{
|
||||
/* extends the range coder to model a Laplace distribution */
|
||||
int value = 0;
|
||||
uint32_t scale, low = 0, center;
|
||||
|
||||
scale = rc->range >> 15;
|
||||
center = rc->value / scale + 1;
|
||||
center = (1 << 15) - FFMIN(center, 1 << 15);
|
||||
|
||||
if (center >= symbol) {
|
||||
value++;
|
||||
low = symbol;
|
||||
symbol = 1 + ((32768 - 32 - symbol) * (16384-decay) >> 15);
|
||||
|
||||
while (symbol > 1 && center >= low + 2 * symbol) {
|
||||
value++;
|
||||
symbol *= 2;
|
||||
low += symbol;
|
||||
symbol = (((symbol - 2) * decay) >> 15) + 1;
|
||||
}
|
||||
|
||||
if (symbol <= 1) {
|
||||
int distance = (center - low) >> 1;
|
||||
value += distance;
|
||||
low += 2 * distance;
|
||||
}
|
||||
|
||||
if (center < low + symbol)
|
||||
value *= -1;
|
||||
else
|
||||
low += symbol;
|
||||
}
|
||||
|
||||
opus_rc_dec_update(rc, scale, low, FFMIN(low + symbol, 32768), 32768);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void ff_opus_rc_enc_laplace(OpusRangeCoder *rc, int *value, uint32_t symbol, int decay)
|
||||
{
|
||||
uint32_t low = symbol;
|
||||
int i = 1, val = FFABS(*value), pos = *value > 0;
|
||||
if (!val) {
|
||||
opus_rc_enc_update(rc, 0, symbol, 1 << 15, 1);
|
||||
return;
|
||||
}
|
||||
symbol = ((32768 - 32 - symbol)*(16384 - decay)) >> 15;
|
||||
for (; i < val && symbol; i++) {
|
||||
low += (symbol << 1) + 2;
|
||||
symbol = (symbol*decay) >> 14;
|
||||
}
|
||||
if (symbol) {
|
||||
low += (++symbol)*pos;
|
||||
} else {
|
||||
const int distance = FFMIN(val - i, (((32768 - low) - !pos) >> 1) - 1);
|
||||
low += pos + (distance << 1);
|
||||
symbol = FFMIN(1, 32768 - low);
|
||||
*value = FFSIGN(*value)*(distance + i);
|
||||
}
|
||||
opus_rc_enc_update(rc, low, low + symbol, 1 << 15, 1);
|
||||
}
|
||||
|
||||
int ff_opus_rc_dec_init(OpusRangeCoder *rc, const uint8_t *data, int size)
|
||||
{
|
||||
int ret = init_get_bits8(&rc->gb, data, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
rc->range = 128;
|
||||
rc->value = 127 - get_bits(&rc->gb, 7);
|
||||
rc->total_bits = 9;
|
||||
opus_rc_dec_normalize(rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_opus_rc_dec_raw_init(OpusRangeCoder *rc, const uint8_t *rightend, uint32_t bytes)
|
||||
{
|
||||
rc->rb.position = rightend;
|
||||
rc->rb.bytes = bytes;
|
||||
rc->rb.cachelen = 0;
|
||||
rc->rb.cacheval = 0;
|
||||
}
|
||||
|
||||
void ff_opus_rc_enc_end(OpusRangeCoder *rc, uint8_t *dst, int size)
|
||||
{
|
||||
int rng_bytes, bits = OPUS_RC_BITS - opus_ilog(rc->range);
|
||||
uint32_t mask = (OPUS_RC_TOP - 1) >> bits;
|
||||
uint32_t end = (rc->value + mask) & ~mask;
|
||||
|
||||
if ((end | mask) >= rc->value + rc->range) {
|
||||
bits++;
|
||||
mask >>= 1;
|
||||
end = (rc->value + mask) & ~mask;
|
||||
}
|
||||
|
||||
/* Finish what's left */
|
||||
while (bits > 0) {
|
||||
opus_rc_enc_carryout(rc, end >> OPUS_RC_SHIFT);
|
||||
end = (end << OPUS_RC_SYM) & (OPUS_RC_TOP - 1);
|
||||
bits -= OPUS_RC_SYM;
|
||||
}
|
||||
|
||||
/* Flush out anything left or marked */
|
||||
if (rc->rem >= 0 || rc->ext > 0)
|
||||
opus_rc_enc_carryout(rc, 0);
|
||||
|
||||
rng_bytes = rc->rng_cur - rc->buf;
|
||||
memcpy(dst, rc->buf, rng_bytes);
|
||||
|
||||
rc->waste = size*8 - (rc->rb.bytes*8 + rc->rb.cachelen) - rng_bytes*8;
|
||||
|
||||
/* Put the rawbits part, if any */
|
||||
if (rc->rb.bytes || rc->rb.cachelen) {
|
||||
int i, lap;
|
||||
uint8_t *rb_src, *rb_dst;
|
||||
ff_opus_rc_put_raw(rc, 0, 32 - rc->rb.cachelen);
|
||||
rb_src = rc->buf + OPUS_MAX_FRAME_SIZE + 12 - rc->rb.bytes;
|
||||
rb_dst = dst + FFMAX(size - rc->rb.bytes, 0);
|
||||
lap = &dst[rng_bytes] - rb_dst;
|
||||
for (i = 0; i < lap; i++)
|
||||
rb_dst[i] |= rb_src[i];
|
||||
memcpy(&rb_dst[lap], &rb_src[lap], FFMAX(rc->rb.bytes - lap, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void ff_opus_rc_enc_init(OpusRangeCoder *rc)
|
||||
{
|
||||
rc->value = 0;
|
||||
rc->range = OPUS_RC_TOP;
|
||||
rc->total_bits = OPUS_RC_BITS + 1;
|
||||
rc->rem = -1;
|
||||
rc->ext = 0;
|
||||
rc->rng_cur = rc->buf;
|
||||
ff_opus_rc_dec_raw_init(rc, rc->buf + OPUS_MAX_FRAME_SIZE + 8, 0);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
* Copyright (c) 2017 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_RC_H
|
||||
#define AVCODEC_OPUS_RC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavcodec/get_bits.h"
|
||||
|
||||
#include "opus.h"
|
||||
|
||||
#define opus_ilog(i) (av_log2(i) + !!(i))
|
||||
|
||||
typedef struct RawBitsContext {
|
||||
const uint8_t *position;
|
||||
uint32_t bytes;
|
||||
uint32_t cachelen;
|
||||
uint32_t cacheval;
|
||||
} RawBitsContext;
|
||||
|
||||
typedef struct OpusRangeCoder {
|
||||
GetBitContext gb;
|
||||
RawBitsContext rb;
|
||||
uint32_t range;
|
||||
uint32_t value;
|
||||
uint32_t total_bits;
|
||||
|
||||
/* Encoder */
|
||||
uint8_t buf[OPUS_MAX_FRAME_SIZE + 12]; /* memcpy vs (memmove + overreading) */
|
||||
uint8_t *rng_cur; /* Current range coded byte */
|
||||
int ext; /* Awaiting propagation */
|
||||
int rem; /* Carryout flag */
|
||||
|
||||
/* Encoding stats */
|
||||
int waste;
|
||||
} OpusRangeCoder;
|
||||
|
||||
/**
|
||||
* CELT: estimate bits of entropy that have thus far been consumed for the
|
||||
* current CELT frame, to integer and fractional (1/8th bit) precision
|
||||
*/
|
||||
static av_always_inline uint32_t opus_rc_tell(const OpusRangeCoder *rc)
|
||||
{
|
||||
return rc->total_bits - av_log2(rc->range) - 1;
|
||||
}
|
||||
|
||||
static av_always_inline uint32_t opus_rc_tell_frac(const OpusRangeCoder *rc)
|
||||
{
|
||||
uint32_t i, total_bits, rcbuffer, range;
|
||||
|
||||
total_bits = rc->total_bits << 3;
|
||||
rcbuffer = av_log2(rc->range) + 1;
|
||||
range = rc->range >> (rcbuffer-16);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
int bit;
|
||||
range = range * range >> 15;
|
||||
bit = range >> 16;
|
||||
rcbuffer = rcbuffer << 1 | bit;
|
||||
range >>= bit;
|
||||
}
|
||||
|
||||
return total_bits - rcbuffer;
|
||||
}
|
||||
|
||||
uint32_t ff_opus_rc_dec_cdf(OpusRangeCoder *rc, const uint16_t *cdf);
|
||||
void ff_opus_rc_enc_cdf(OpusRangeCoder *rc, int val, const uint16_t *cdf);
|
||||
|
||||
uint32_t ff_opus_rc_dec_log(OpusRangeCoder *rc, uint32_t bits);
|
||||
void ff_opus_rc_enc_log(OpusRangeCoder *rc, int val, uint32_t bits);
|
||||
|
||||
uint32_t ff_opus_rc_dec_uint_step(OpusRangeCoder *rc, int k0);
|
||||
void ff_opus_rc_enc_uint_step(OpusRangeCoder *rc, uint32_t val, int k0);
|
||||
|
||||
uint32_t ff_opus_rc_dec_uint_tri(OpusRangeCoder *rc, int qn);
|
||||
void ff_opus_rc_enc_uint_tri(OpusRangeCoder *rc, uint32_t k, int qn);
|
||||
|
||||
uint32_t ff_opus_rc_dec_uint(OpusRangeCoder *rc, uint32_t size);
|
||||
void ff_opus_rc_enc_uint(OpusRangeCoder *rc, uint32_t val, uint32_t size);
|
||||
|
||||
uint32_t ff_opus_rc_get_raw(OpusRangeCoder *rc, uint32_t count);
|
||||
void ff_opus_rc_put_raw(OpusRangeCoder *rc, uint32_t val, uint32_t count);
|
||||
|
||||
int ff_opus_rc_dec_laplace(OpusRangeCoder *rc, uint32_t symbol, int decay);
|
||||
void ff_opus_rc_enc_laplace(OpusRangeCoder *rc, int *value, uint32_t symbol, int decay);
|
||||
|
||||
int ff_opus_rc_dec_init(OpusRangeCoder *rc, const uint8_t *data, int size);
|
||||
void ff_opus_rc_dec_raw_init(OpusRangeCoder *rc, const uint8_t *rightend, uint32_t bytes);
|
||||
|
||||
void ff_opus_rc_enc_end(OpusRangeCoder *rc, uint8_t *dst, int size);
|
||||
void ff_opus_rc_enc_init(OpusRangeCoder *rc);
|
||||
|
||||
#define OPUS_RC_CHECKPOINT_UPDATE(rc) \
|
||||
rc_rollback_bits = opus_rc_tell_frac(rc); \
|
||||
rc_rollback_ctx = *rc
|
||||
|
||||
#define OPUS_RC_CHECKPOINT_SPAWN(rc) \
|
||||
uint32_t rc_rollback_bits = opus_rc_tell_frac(rc); \
|
||||
OpusRangeCoder rc_rollback_ctx = *rc \
|
||||
|
||||
#define OPUS_RC_CHECKPOINT_BITS(rc) \
|
||||
(opus_rc_tell_frac(rc) - rc_rollback_bits)
|
||||
|
||||
#define OPUS_RC_CHECKPOINT_ROLLBACK(rc) \
|
||||
memcpy(rc, &rc_rollback_ctx, sizeof(OpusRangeCoder)); \
|
||||
|
||||
#endif /* AVCODEC_OPUS_RC_H */
|
||||
@@ -0,0 +1,907 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
*
|
||||
* 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
|
||||
* Opus SILK decoder
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/mem.h"
|
||||
#include "mathops.h"
|
||||
#include "opus.h"
|
||||
#include "rc.h"
|
||||
#include "silk.h"
|
||||
#include "tab.h"
|
||||
|
||||
#define ROUND_MULL(a,b,s) (((MUL64(a, b) >> ((s) - 1)) + 1) >> 1)
|
||||
|
||||
typedef struct SilkFrame {
|
||||
int coded;
|
||||
int log_gain;
|
||||
int16_t nlsf[16];
|
||||
float lpc[16];
|
||||
|
||||
float output [2 * SILK_HISTORY];
|
||||
float lpc_history[2 * SILK_HISTORY];
|
||||
int primarylag;
|
||||
|
||||
int prev_voiced;
|
||||
} SilkFrame;
|
||||
|
||||
struct SilkContext {
|
||||
void *logctx;
|
||||
int output_channels;
|
||||
|
||||
int midonly;
|
||||
int subframes;
|
||||
int sflength;
|
||||
int flength;
|
||||
int nlsf_interp_factor;
|
||||
|
||||
enum OpusBandwidth bandwidth;
|
||||
int wb;
|
||||
|
||||
SilkFrame frame[2];
|
||||
float prev_stereo_weights[2];
|
||||
float stereo_weights[2];
|
||||
|
||||
int prev_coded_channels;
|
||||
};
|
||||
|
||||
static inline void silk_stabilize_lsf(int16_t nlsf[16], int order, const uint16_t min_delta[17])
|
||||
{
|
||||
int pass, i;
|
||||
for (pass = 0; pass < 20; pass++) {
|
||||
int k, min_diff = 0;
|
||||
for (i = 0; i < order+1; i++) {
|
||||
int low = i != 0 ? nlsf[i-1] : 0;
|
||||
int high = i != order ? nlsf[i] : 32768;
|
||||
int diff = (high - low) - (min_delta[i]);
|
||||
|
||||
if (diff < min_diff) {
|
||||
min_diff = diff;
|
||||
k = i;
|
||||
|
||||
if (pass == 20)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (min_diff == 0) /* no issues; stabilized */
|
||||
return;
|
||||
|
||||
/* wiggle one or two LSFs */
|
||||
if (k == 0) {
|
||||
/* repel away from lower bound */
|
||||
nlsf[0] = min_delta[0];
|
||||
} else if (k == order) {
|
||||
/* repel away from higher bound */
|
||||
nlsf[order-1] = 32768 - min_delta[order];
|
||||
} else {
|
||||
/* repel away from current position */
|
||||
int min_center = 0, max_center = 32768, center_val;
|
||||
|
||||
/* lower extent */
|
||||
for (i = 0; i < k; i++)
|
||||
min_center += min_delta[i];
|
||||
min_center += min_delta[k] >> 1;
|
||||
|
||||
/* upper extent */
|
||||
for (i = order; i > k; i--)
|
||||
max_center -= min_delta[i];
|
||||
max_center -= min_delta[k] >> 1;
|
||||
|
||||
/* move apart */
|
||||
center_val = nlsf[k - 1] + nlsf[k];
|
||||
center_val = (center_val >> 1) + (center_val & 1); // rounded divide by 2
|
||||
center_val = FFMIN(max_center, FFMAX(min_center, center_val));
|
||||
|
||||
nlsf[k - 1] = center_val - (min_delta[k] >> 1);
|
||||
nlsf[k] = nlsf[k - 1] + min_delta[k];
|
||||
}
|
||||
}
|
||||
|
||||
/* resort to the fall-back method, the standard method for LSF stabilization */
|
||||
|
||||
/* sort; as the LSFs should be nearly sorted, use insertion sort */
|
||||
for (i = 1; i < order; i++) {
|
||||
int j, value = nlsf[i];
|
||||
for (j = i - 1; j >= 0 && nlsf[j] > value; j--)
|
||||
nlsf[j + 1] = nlsf[j];
|
||||
nlsf[j + 1] = value;
|
||||
}
|
||||
|
||||
/* push forwards to increase distance */
|
||||
if (nlsf[0] < min_delta[0])
|
||||
nlsf[0] = min_delta[0];
|
||||
for (i = 1; i < order; i++)
|
||||
nlsf[i] = FFMAX(nlsf[i], FFMIN(nlsf[i - 1] + min_delta[i], 32767));
|
||||
|
||||
/* push backwards to increase distance */
|
||||
if (nlsf[order-1] > 32768 - min_delta[order])
|
||||
nlsf[order-1] = 32768 - min_delta[order];
|
||||
for (i = order-2; i >= 0; i--)
|
||||
if (nlsf[i] > nlsf[i + 1] - min_delta[i+1])
|
||||
nlsf[i] = nlsf[i + 1] - min_delta[i+1];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int silk_is_lpc_stable(const int16_t lpc[16], int order)
|
||||
{
|
||||
int k, j, DC_resp = 0;
|
||||
int32_t lpc32[2][16]; // Q24
|
||||
int totalinvgain = 1 << 30; // 1.0 in Q30
|
||||
int32_t *row = lpc32[0], *prevrow;
|
||||
|
||||
/* initialize the first row for the Levinson recursion */
|
||||
for (k = 0; k < order; k++) {
|
||||
DC_resp += lpc[k];
|
||||
row[k] = lpc[k] * 4096;
|
||||
}
|
||||
|
||||
if (DC_resp >= 4096)
|
||||
return 0;
|
||||
|
||||
/* check if prediction gain pushes any coefficients too far */
|
||||
for (k = order - 1; 1; k--) {
|
||||
int rc; // Q31; reflection coefficient
|
||||
int gaindiv; // Q30; inverse of the gain (the divisor)
|
||||
int gain; // gain for this reflection coefficient
|
||||
int fbits; // fractional bits used for the gain
|
||||
int error; // Q29; estimate of the error of our partial estimate of 1/gaindiv
|
||||
|
||||
if (FFABS(row[k]) > 16773022)
|
||||
return 0;
|
||||
|
||||
rc = -(row[k] * 128);
|
||||
gaindiv = (1 << 30) - MULH(rc, rc);
|
||||
|
||||
totalinvgain = MULH(totalinvgain, gaindiv) << 2;
|
||||
if (k == 0)
|
||||
return (totalinvgain >= 107374);
|
||||
|
||||
/* approximate 1.0/gaindiv */
|
||||
fbits = opus_ilog(gaindiv);
|
||||
gain = ((1 << 29) - 1) / (gaindiv >> (fbits + 1 - 16)); // Q<fbits-16>
|
||||
error = (1 << 29) - MULL(gaindiv << (15 + 16 - fbits), gain, 16);
|
||||
gain = ((gain << 16) + (error * gain >> 13));
|
||||
|
||||
/* switch to the next row of the LPC coefficients */
|
||||
prevrow = row;
|
||||
row = lpc32[k & 1];
|
||||
|
||||
for (j = 0; j < k; j++) {
|
||||
int x = av_sat_sub32(prevrow[j], ROUND_MULL(prevrow[k - j - 1], rc, 31));
|
||||
int64_t tmp = ROUND_MULL(x, gain, fbits);
|
||||
|
||||
/* per RFC 8251 section 6, if this calculation overflows, the filter
|
||||
is considered unstable. */
|
||||
if (tmp < INT32_MIN || tmp > INT32_MAX)
|
||||
return 0;
|
||||
|
||||
row[j] = (int32_t)tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void silk_lsp2poly(const int32_t lsp[/* 2 * half_order - 1 */],
|
||||
int32_t pol[/* half_order + 1 */], int half_order)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
pol[0] = 65536; // 1.0 in Q16
|
||||
pol[1] = -lsp[0];
|
||||
|
||||
for (i = 1; i < half_order; i++) {
|
||||
pol[i + 1] = pol[i - 1] * 2 - ROUND_MULL(lsp[2 * i], pol[i], 16);
|
||||
for (j = i; j > 1; j--)
|
||||
pol[j] += pol[j - 2] - ROUND_MULL(lsp[2 * i], pol[j - 1], 16);
|
||||
|
||||
pol[1] -= lsp[2 * i];
|
||||
}
|
||||
}
|
||||
|
||||
static void silk_lsf2lpc(const int16_t nlsf[16], float lpcf[16], int order)
|
||||
{
|
||||
int i, k;
|
||||
int32_t lsp[16]; // Q17; 2*cos(LSF)
|
||||
int32_t p[9], q[9]; // Q16
|
||||
int32_t lpc32[16]; // Q17
|
||||
int16_t lpc[16]; // Q12
|
||||
|
||||
/* convert the LSFs to LSPs, i.e. 2*cos(LSF) */
|
||||
for (k = 0; k < order; k++) {
|
||||
int index = nlsf[k] >> 8;
|
||||
int offset = nlsf[k] & 255;
|
||||
int k2 = (order == 10) ? ff_silk_lsf_ordering_nbmb[k] : ff_silk_lsf_ordering_wb[k];
|
||||
|
||||
/* interpolate and round */
|
||||
lsp[k2] = ff_silk_cosine[index] * 256;
|
||||
lsp[k2] += (ff_silk_cosine[index + 1] - ff_silk_cosine[index]) * offset;
|
||||
lsp[k2] = (lsp[k2] + 4) >> 3;
|
||||
}
|
||||
|
||||
silk_lsp2poly(lsp , p, order >> 1);
|
||||
silk_lsp2poly(lsp + 1, q, order >> 1);
|
||||
|
||||
/* reconstruct A(z) */
|
||||
for (k = 0; k < order>>1; k++) {
|
||||
int32_t p_tmp = p[k + 1] + p[k];
|
||||
int32_t q_tmp = q[k + 1] - q[k];
|
||||
lpc32[k] = -q_tmp - p_tmp;
|
||||
lpc32[order-k-1] = q_tmp - p_tmp;
|
||||
}
|
||||
|
||||
/* limit the range of the LPC coefficients to each fit within an int16_t */
|
||||
for (i = 0; i < 10; i++) {
|
||||
int j;
|
||||
unsigned int maxabs = 0;
|
||||
for (j = 0, k = 0; j < order; j++) {
|
||||
unsigned int x = FFABS(lpc32[k]);
|
||||
if (x > maxabs) {
|
||||
maxabs = x; // Q17
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
|
||||
maxabs = (maxabs + 16) >> 5; // convert to Q12
|
||||
|
||||
if (maxabs > 32767) {
|
||||
/* perform bandwidth expansion */
|
||||
unsigned int chirp, chirp_base; // Q16
|
||||
maxabs = FFMIN(maxabs, 163838); // anything above this overflows chirp's numerator
|
||||
chirp_base = chirp = 65470 - ((maxabs - 32767) << 14) / ((maxabs * (k+1)) >> 2);
|
||||
|
||||
for (k = 0; k < order; k++) {
|
||||
lpc32[k] = ROUND_MULL(lpc32[k], chirp, 16);
|
||||
chirp = (chirp_base * chirp + 32768) >> 16;
|
||||
}
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (i == 10) {
|
||||
/* time's up: just clamp */
|
||||
for (k = 0; k < order; k++) {
|
||||
int x = (lpc32[k] + 16) >> 5;
|
||||
lpc[k] = av_clip_int16(x);
|
||||
lpc32[k] = lpc[k] << 5; // shortcut mandated by the spec; drops lower 5 bits
|
||||
}
|
||||
} else {
|
||||
for (k = 0; k < order; k++)
|
||||
lpc[k] = (lpc32[k] + 16) >> 5;
|
||||
}
|
||||
|
||||
/* if the prediction gain causes the LPC filter to become unstable,
|
||||
apply further bandwidth expansion on the Q17 coefficients */
|
||||
for (i = 1; i <= 16 && !silk_is_lpc_stable(lpc, order); i++) {
|
||||
unsigned int chirp, chirp_base;
|
||||
chirp_base = chirp = 65536 - (1 << i);
|
||||
|
||||
for (k = 0; k < order; k++) {
|
||||
lpc32[k] = ROUND_MULL(lpc32[k], chirp, 16);
|
||||
lpc[k] = (lpc32[k] + 16) >> 5;
|
||||
chirp = (chirp_base * chirp + 32768) >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < order; i++)
|
||||
lpcf[i] = lpc[i] / 4096.0f;
|
||||
}
|
||||
|
||||
static inline void silk_decode_lpc(SilkContext *s, SilkFrame *frame,
|
||||
OpusRangeCoder *rc,
|
||||
float lpc_leadin[16], float lpc[16],
|
||||
int *lpc_order, int *has_lpc_leadin, int voiced)
|
||||
{
|
||||
int i;
|
||||
int order; // order of the LP polynomial; 10 for NB/MB and 16 for WB
|
||||
int8_t lsf_i1, lsf_i2[16]; // stage-1 and stage-2 codebook indices
|
||||
int16_t lsf_res[16]; // residual as a Q10 value
|
||||
int16_t nlsf[16]; // Q15
|
||||
|
||||
*lpc_order = order = s->wb ? 16 : 10;
|
||||
|
||||
/* obtain LSF stage-1 and stage-2 indices */
|
||||
lsf_i1 = ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_s1[s->wb][voiced]);
|
||||
for (i = 0; i < order; i++) {
|
||||
int index = s->wb ? ff_silk_lsf_s2_model_sel_wb [lsf_i1][i] :
|
||||
ff_silk_lsf_s2_model_sel_nbmb[lsf_i1][i];
|
||||
lsf_i2[i] = ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_s2[index]) - 4;
|
||||
if (lsf_i2[i] == -4)
|
||||
lsf_i2[i] -= ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_s2_ext);
|
||||
else if (lsf_i2[i] == 4)
|
||||
lsf_i2[i] += ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_s2_ext);
|
||||
}
|
||||
|
||||
/* reverse the backwards-prediction step */
|
||||
for (i = order - 1; i >= 0; i--) {
|
||||
int qstep = s->wb ? 9830 : 11796;
|
||||
|
||||
lsf_res[i] = lsf_i2[i] * 1024;
|
||||
if (lsf_i2[i] < 0) lsf_res[i] += 102;
|
||||
else if (lsf_i2[i] > 0) lsf_res[i] -= 102;
|
||||
lsf_res[i] = (lsf_res[i] * qstep) >> 16;
|
||||
|
||||
if (i + 1 < order) {
|
||||
int weight = s->wb ? ff_silk_lsf_pred_weights_wb [ff_silk_lsf_weight_sel_wb [lsf_i1][i]][i] :
|
||||
ff_silk_lsf_pred_weights_nbmb[ff_silk_lsf_weight_sel_nbmb[lsf_i1][i]][i];
|
||||
lsf_res[i] += (lsf_res[i+1] * weight) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* reconstruct the NLSF coefficients from the supplied indices */
|
||||
for (i = 0; i < order; i++) {
|
||||
const uint8_t * codebook = s->wb ? ff_silk_lsf_codebook_wb [lsf_i1] :
|
||||
ff_silk_lsf_codebook_nbmb[lsf_i1];
|
||||
int cur, prev, next, weight_sq, weight, ipart, fpart, y, value;
|
||||
|
||||
/* find the weight of the residual */
|
||||
/* TODO: precompute */
|
||||
cur = codebook[i];
|
||||
prev = i ? codebook[i - 1] : 0;
|
||||
next = i + 1 < order ? codebook[i + 1] : 256;
|
||||
weight_sq = (1024 / (cur - prev) + 1024 / (next - cur)) << 16;
|
||||
|
||||
/* approximate square-root with mandated fixed-point arithmetic */
|
||||
ipart = opus_ilog(weight_sq);
|
||||
fpart = (weight_sq >> (ipart-8)) & 127;
|
||||
y = ((ipart & 1) ? 32768 : 46214) >> ((32 - ipart)>>1);
|
||||
weight = y + ((213 * fpart * y) >> 16);
|
||||
|
||||
value = cur * 128 + (lsf_res[i] * 16384) / weight;
|
||||
nlsf[i] = av_clip_uintp2(value, 15);
|
||||
}
|
||||
|
||||
/* stabilize the NLSF coefficients */
|
||||
silk_stabilize_lsf(nlsf, order, s->wb ? ff_silk_lsf_min_spacing_wb :
|
||||
ff_silk_lsf_min_spacing_nbmb);
|
||||
|
||||
/* produce an interpolation for the first 2 subframes, */
|
||||
/* and then convert both sets of NLSFs to LPC coefficients */
|
||||
*has_lpc_leadin = 0;
|
||||
if (s->subframes == 4) {
|
||||
int offset = ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_interpolation_offset);
|
||||
if (offset != 4 && frame->coded) {
|
||||
*has_lpc_leadin = 1;
|
||||
if (offset != 0) {
|
||||
int16_t nlsf_leadin[16];
|
||||
for (i = 0; i < order; i++)
|
||||
nlsf_leadin[i] = frame->nlsf[i] +
|
||||
((nlsf[i] - frame->nlsf[i]) * offset >> 2);
|
||||
silk_lsf2lpc(nlsf_leadin, lpc_leadin, order);
|
||||
} else /* avoid re-computation for a (roughly) 1-in-4 occurrence */
|
||||
memcpy(lpc_leadin, frame->lpc, 16 * sizeof(float));
|
||||
} else
|
||||
offset = 4;
|
||||
s->nlsf_interp_factor = offset;
|
||||
|
||||
silk_lsf2lpc(nlsf, lpc, order);
|
||||
} else {
|
||||
s->nlsf_interp_factor = 4;
|
||||
silk_lsf2lpc(nlsf, lpc, order);
|
||||
}
|
||||
|
||||
memcpy(frame->nlsf, nlsf, order * sizeof(nlsf[0]));
|
||||
memcpy(frame->lpc, lpc, order * sizeof(lpc[0]));
|
||||
}
|
||||
|
||||
static inline void silk_count_children(OpusRangeCoder *rc, int model, int32_t total,
|
||||
int32_t child[2])
|
||||
{
|
||||
if (total != 0) {
|
||||
child[0] = ff_opus_rc_dec_cdf(rc,
|
||||
ff_silk_model_pulse_location[model] + (((total - 1 + 5) * (total - 1)) >> 1));
|
||||
child[1] = total - child[0];
|
||||
} else {
|
||||
child[0] = 0;
|
||||
child[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void silk_decode_excitation(SilkContext *s, OpusRangeCoder *rc,
|
||||
float* excitationf,
|
||||
int qoffset_high, int active, int voiced)
|
||||
{
|
||||
int i;
|
||||
uint32_t seed;
|
||||
int shellblocks;
|
||||
int ratelevel;
|
||||
uint8_t pulsecount[20]; // total pulses in each shell block
|
||||
uint8_t lsbcount[20] = {0}; // raw lsbits defined for each pulse in each shell block
|
||||
int32_t excitation[320]; // Q23
|
||||
|
||||
/* excitation parameters */
|
||||
seed = ff_opus_rc_dec_cdf(rc, ff_silk_model_lcg_seed);
|
||||
shellblocks = ff_silk_shell_blocks[s->bandwidth][s->subframes >> 2];
|
||||
ratelevel = ff_opus_rc_dec_cdf(rc, ff_silk_model_exc_rate[voiced]);
|
||||
|
||||
for (i = 0; i < shellblocks; i++) {
|
||||
pulsecount[i] = ff_opus_rc_dec_cdf(rc, ff_silk_model_pulse_count[ratelevel]);
|
||||
if (pulsecount[i] == 17) {
|
||||
while (pulsecount[i] == 17 && ++lsbcount[i] != 10)
|
||||
pulsecount[i] = ff_opus_rc_dec_cdf(rc, ff_silk_model_pulse_count[9]);
|
||||
if (lsbcount[i] == 10)
|
||||
pulsecount[i] = ff_opus_rc_dec_cdf(rc, ff_silk_model_pulse_count[10]);
|
||||
}
|
||||
}
|
||||
|
||||
/* decode pulse locations using PVQ */
|
||||
for (i = 0; i < shellblocks; i++) {
|
||||
if (pulsecount[i] != 0) {
|
||||
int a, b, c, d;
|
||||
int32_t * location = excitation + 16*i;
|
||||
int32_t branch[4][2];
|
||||
branch[0][0] = pulsecount[i];
|
||||
|
||||
/* unrolled tail recursion */
|
||||
for (a = 0; a < 1; a++) {
|
||||
silk_count_children(rc, 0, branch[0][a], branch[1]);
|
||||
for (b = 0; b < 2; b++) {
|
||||
silk_count_children(rc, 1, branch[1][b], branch[2]);
|
||||
for (c = 0; c < 2; c++) {
|
||||
silk_count_children(rc, 2, branch[2][c], branch[3]);
|
||||
for (d = 0; d < 2; d++) {
|
||||
silk_count_children(rc, 3, branch[3][d], location);
|
||||
location += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
memset(excitation + 16*i, 0, 16*sizeof(int32_t));
|
||||
}
|
||||
|
||||
/* decode least significant bits */
|
||||
for (i = 0; i < shellblocks << 4; i++) {
|
||||
int bit;
|
||||
for (bit = 0; bit < lsbcount[i >> 4]; bit++)
|
||||
excitation[i] = (excitation[i] << 1) |
|
||||
ff_opus_rc_dec_cdf(rc, ff_silk_model_excitation_lsb);
|
||||
}
|
||||
|
||||
/* decode signs */
|
||||
for (i = 0; i < shellblocks << 4; i++) {
|
||||
if (excitation[i] != 0) {
|
||||
int sign = ff_opus_rc_dec_cdf(rc, ff_silk_model_excitation_sign[active +
|
||||
voiced][qoffset_high][FFMIN(pulsecount[i >> 4], 6)]);
|
||||
if (sign == 0)
|
||||
excitation[i] *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* assemble the excitation */
|
||||
for (i = 0; i < shellblocks << 4; i++) {
|
||||
int value = excitation[i];
|
||||
excitation[i] = value * 256 | ff_silk_quant_offset[voiced][qoffset_high];
|
||||
if (value < 0) excitation[i] += 20;
|
||||
else if (value > 0) excitation[i] -= 20;
|
||||
|
||||
/* invert samples pseudorandomly */
|
||||
seed = 196314165 * seed + 907633515;
|
||||
if (seed & 0x80000000)
|
||||
excitation[i] *= -1;
|
||||
seed += value;
|
||||
|
||||
excitationf[i] = excitation[i] / 8388608.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/** Maximum residual history according to 4.2.7.6.1 */
|
||||
#define SILK_MAX_LAG (288 + LTP_ORDER / 2)
|
||||
|
||||
/** Order of the LTP filter */
|
||||
#define LTP_ORDER 5
|
||||
|
||||
static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
|
||||
int frame_num, int channel, int coded_channels,
|
||||
int active, int active1, int redundant)
|
||||
{
|
||||
/* per frame */
|
||||
int voiced; // combines with active to indicate inactive, active, or active+voiced
|
||||
int qoffset_high;
|
||||
int order; // order of the LPC coefficients
|
||||
float lpc_leadin[16], lpc_body[16], residual[SILK_MAX_LAG + SILK_HISTORY];
|
||||
int has_lpc_leadin;
|
||||
float ltpscale;
|
||||
|
||||
/* per subframe */
|
||||
struct {
|
||||
float gain;
|
||||
int pitchlag;
|
||||
float ltptaps[5];
|
||||
} sf[4];
|
||||
|
||||
SilkFrame * const frame = s->frame + channel;
|
||||
|
||||
int i;
|
||||
|
||||
/* obtain stereo weights */
|
||||
if (coded_channels == 2 && channel == 0) {
|
||||
int n, wi[2], ws[2], w[2];
|
||||
n = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s1);
|
||||
wi[0] = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s2) + 3 * (n / 5);
|
||||
ws[0] = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s3);
|
||||
wi[1] = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s2) + 3 * (n % 5);
|
||||
ws[1] = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s3);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
w[i] = ff_silk_stereo_weights[wi[i]] +
|
||||
(((ff_silk_stereo_weights[wi[i] + 1] - ff_silk_stereo_weights[wi[i]]) * 6554) >> 16)
|
||||
* (ws[i]*2 + 1);
|
||||
|
||||
s->stereo_weights[0] = (w[0] - w[1]) / 8192.0;
|
||||
s->stereo_weights[1] = w[1] / 8192.0;
|
||||
|
||||
/* and read the mid-only flag */
|
||||
s->midonly = active1 ? 0 : ff_opus_rc_dec_cdf(rc, ff_silk_model_mid_only);
|
||||
}
|
||||
|
||||
/* obtain frame type */
|
||||
if (!active) {
|
||||
qoffset_high = ff_opus_rc_dec_cdf(rc, ff_silk_model_frame_type_inactive);
|
||||
voiced = 0;
|
||||
} else {
|
||||
int type = ff_opus_rc_dec_cdf(rc, ff_silk_model_frame_type_active);
|
||||
qoffset_high = type & 1;
|
||||
voiced = type >> 1;
|
||||
}
|
||||
|
||||
/* obtain subframe quantization gains */
|
||||
for (i = 0; i < s->subframes; i++) {
|
||||
int log_gain; //Q7
|
||||
int ipart, fpart, lingain;
|
||||
|
||||
if (i == 0 && (frame_num == 0 || !frame->coded)) {
|
||||
/* gain is coded absolute */
|
||||
int x = ff_opus_rc_dec_cdf(rc, ff_silk_model_gain_highbits[active + voiced]);
|
||||
log_gain = (x<<3) | ff_opus_rc_dec_cdf(rc, ff_silk_model_gain_lowbits);
|
||||
|
||||
if (frame->coded)
|
||||
log_gain = FFMAX(log_gain, frame->log_gain - 16);
|
||||
} else {
|
||||
/* gain is coded relative */
|
||||
int delta_gain = ff_opus_rc_dec_cdf(rc, ff_silk_model_gain_delta);
|
||||
log_gain = av_clip_uintp2(FFMAX((delta_gain<<1) - 16,
|
||||
frame->log_gain + delta_gain - 4), 6);
|
||||
}
|
||||
|
||||
frame->log_gain = log_gain;
|
||||
|
||||
/* approximate 2**(x/128) with a Q7 (i.e. non-integer) input */
|
||||
log_gain = (log_gain * 0x1D1C71 >> 16) + 2090;
|
||||
ipart = log_gain >> 7;
|
||||
fpart = log_gain & 127;
|
||||
lingain = (1 << ipart) + ((-174 * fpart * (128-fpart) >>16) + fpart) * ((1<<ipart) >> 7);
|
||||
sf[i].gain = lingain / 65536.0f;
|
||||
}
|
||||
|
||||
/* obtain LPC filter coefficients */
|
||||
silk_decode_lpc(s, frame, rc, lpc_leadin, lpc_body, &order, &has_lpc_leadin, voiced);
|
||||
|
||||
/* obtain pitch lags, if this is a voiced frame */
|
||||
if (voiced) {
|
||||
int lag_absolute = (!frame_num || !frame->prev_voiced);
|
||||
int primarylag; // primary pitch lag for the entire SILK frame
|
||||
int ltpfilter;
|
||||
const int8_t * offsets;
|
||||
|
||||
if (!lag_absolute) {
|
||||
int delta = ff_opus_rc_dec_cdf(rc, ff_silk_model_pitch_delta);
|
||||
if (delta)
|
||||
primarylag = frame->primarylag + delta - 9;
|
||||
else
|
||||
lag_absolute = 1;
|
||||
}
|
||||
|
||||
if (lag_absolute) {
|
||||
/* primary lag is coded absolute */
|
||||
int highbits, lowbits;
|
||||
static const uint16_t * const model[] = {
|
||||
ff_silk_model_pitch_lowbits_nb, ff_silk_model_pitch_lowbits_mb,
|
||||
ff_silk_model_pitch_lowbits_wb
|
||||
};
|
||||
highbits = ff_opus_rc_dec_cdf(rc, ff_silk_model_pitch_highbits);
|
||||
lowbits = ff_opus_rc_dec_cdf(rc, model[s->bandwidth]);
|
||||
|
||||
primarylag = ff_silk_pitch_min_lag[s->bandwidth] +
|
||||
highbits*ff_silk_pitch_scale[s->bandwidth] + lowbits;
|
||||
}
|
||||
frame->primarylag = primarylag;
|
||||
|
||||
if (s->subframes == 2)
|
||||
offsets = (s->bandwidth == OPUS_BANDWIDTH_NARROWBAND)
|
||||
? ff_silk_pitch_offset_nb10ms[ff_opus_rc_dec_cdf(rc,
|
||||
ff_silk_model_pitch_contour_nb10ms)]
|
||||
: ff_silk_pitch_offset_mbwb10ms[ff_opus_rc_dec_cdf(rc,
|
||||
ff_silk_model_pitch_contour_mbwb10ms)];
|
||||
else
|
||||
offsets = (s->bandwidth == OPUS_BANDWIDTH_NARROWBAND)
|
||||
? ff_silk_pitch_offset_nb20ms[ff_opus_rc_dec_cdf(rc,
|
||||
ff_silk_model_pitch_contour_nb20ms)]
|
||||
: ff_silk_pitch_offset_mbwb20ms[ff_opus_rc_dec_cdf(rc,
|
||||
ff_silk_model_pitch_contour_mbwb20ms)];
|
||||
|
||||
for (i = 0; i < s->subframes; i++)
|
||||
sf[i].pitchlag = av_clip(primarylag + offsets[i],
|
||||
ff_silk_pitch_min_lag[s->bandwidth],
|
||||
ff_silk_pitch_max_lag[s->bandwidth]);
|
||||
|
||||
/* obtain LTP filter coefficients */
|
||||
ltpfilter = ff_opus_rc_dec_cdf(rc, ff_silk_model_ltp_filter);
|
||||
for (i = 0; i < s->subframes; i++) {
|
||||
int index, j;
|
||||
static const uint16_t * const filter_sel[] = {
|
||||
ff_silk_model_ltp_filter0_sel, ff_silk_model_ltp_filter1_sel,
|
||||
ff_silk_model_ltp_filter2_sel
|
||||
};
|
||||
static const int8_t (* const filter_taps[])[5] = {
|
||||
ff_silk_ltp_filter0_taps, ff_silk_ltp_filter1_taps, ff_silk_ltp_filter2_taps
|
||||
};
|
||||
index = ff_opus_rc_dec_cdf(rc, filter_sel[ltpfilter]);
|
||||
for (j = 0; j < 5; j++)
|
||||
sf[i].ltptaps[j] = filter_taps[ltpfilter][index][j] / 128.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* obtain LTP scale factor */
|
||||
if (voiced && frame_num == 0)
|
||||
ltpscale = ff_silk_ltp_scale_factor[ff_opus_rc_dec_cdf(rc,
|
||||
ff_silk_model_ltp_scale_index)] / 16384.0f;
|
||||
else ltpscale = 15565.0f/16384.0f;
|
||||
|
||||
/* generate the excitation signal for the entire frame */
|
||||
silk_decode_excitation(s, rc, residual + SILK_MAX_LAG, qoffset_high,
|
||||
active, voiced);
|
||||
|
||||
/* skip synthesising the output if we do not need it */
|
||||
// TODO: implement error recovery
|
||||
if (s->output_channels == channel || redundant)
|
||||
return;
|
||||
|
||||
/* generate the output signal */
|
||||
for (i = 0; i < s->subframes; i++) {
|
||||
const float * lpc_coeff = (i < 2 && has_lpc_leadin) ? lpc_leadin : lpc_body;
|
||||
float *dst = frame->output + SILK_HISTORY + i * s->sflength;
|
||||
float *resptr = residual + SILK_MAX_LAG + i * s->sflength;
|
||||
float *lpc = frame->lpc_history + SILK_HISTORY + i * s->sflength;
|
||||
float sum;
|
||||
int j, k;
|
||||
|
||||
if (voiced) {
|
||||
int out_end;
|
||||
float scale;
|
||||
|
||||
if (i < 2 || s->nlsf_interp_factor == 4) {
|
||||
out_end = -i * s->sflength;
|
||||
scale = ltpscale;
|
||||
} else {
|
||||
out_end = -(i - 2) * s->sflength;
|
||||
scale = 1.0f;
|
||||
}
|
||||
|
||||
/* when the LPC coefficients change, a re-whitening filter is used */
|
||||
/* to produce a residual that accounts for the change */
|
||||
for (j = - sf[i].pitchlag - LTP_ORDER/2; j < out_end; j++) {
|
||||
sum = dst[j];
|
||||
for (k = 0; k < order; k++)
|
||||
sum -= lpc_coeff[k] * dst[j - k - 1];
|
||||
resptr[j] = av_clipf(sum, -1.0f, 1.0f) * scale / sf[i].gain;
|
||||
}
|
||||
|
||||
if (out_end) {
|
||||
float rescale = sf[i-1].gain / sf[i].gain;
|
||||
for (j = out_end; j < 0; j++)
|
||||
resptr[j] *= rescale;
|
||||
}
|
||||
|
||||
/* LTP synthesis */
|
||||
for (j = 0; j < s->sflength; j++) {
|
||||
sum = resptr[j];
|
||||
for (k = 0; k < LTP_ORDER; k++)
|
||||
sum += sf[i].ltptaps[k] * resptr[j - sf[i].pitchlag + LTP_ORDER/2 - k];
|
||||
resptr[j] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* LPC synthesis */
|
||||
for (j = 0; j < s->sflength; j++) {
|
||||
sum = resptr[j] * sf[i].gain;
|
||||
for (k = 1; k <= order; k++)
|
||||
sum += lpc_coeff[k - 1] * lpc[j - k];
|
||||
|
||||
lpc[j] = sum;
|
||||
dst[j] = av_clipf(sum, -1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
frame->prev_voiced = voiced;
|
||||
memmove(frame->lpc_history, frame->lpc_history + s->flength, SILK_HISTORY * sizeof(float));
|
||||
memmove(frame->output, frame->output + s->flength, SILK_HISTORY * sizeof(float));
|
||||
|
||||
frame->coded = 1;
|
||||
}
|
||||
|
||||
static void silk_unmix_ms(SilkContext *s, float *l, float *r)
|
||||
{
|
||||
float *mid = s->frame[0].output + SILK_HISTORY - s->flength;
|
||||
float *side = s->frame[1].output + SILK_HISTORY - s->flength;
|
||||
float w0_prev = s->prev_stereo_weights[0];
|
||||
float w1_prev = s->prev_stereo_weights[1];
|
||||
float w0 = s->stereo_weights[0];
|
||||
float w1 = s->stereo_weights[1];
|
||||
int n1 = ff_silk_stereo_interp_len[s->bandwidth];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n1; i++) {
|
||||
float interp0 = w0_prev + i * (w0 - w0_prev) / n1;
|
||||
float interp1 = w1_prev + i * (w1 - w1_prev) / n1;
|
||||
float p0 = 0.25 * (mid[i - 2] + 2 * mid[i - 1] + mid[i]);
|
||||
|
||||
l[i] = av_clipf((1 + interp1) * mid[i - 1] + side[i - 1] + interp0 * p0, -1.0, 1.0);
|
||||
r[i] = av_clipf((1 - interp1) * mid[i - 1] - side[i - 1] - interp0 * p0, -1.0, 1.0);
|
||||
}
|
||||
|
||||
for (; i < s->flength; i++) {
|
||||
float p0 = 0.25 * (mid[i - 2] + 2 * mid[i - 1] + mid[i]);
|
||||
|
||||
l[i] = av_clipf((1 + w1) * mid[i - 1] + side[i - 1] + w0 * p0, -1.0, 1.0);
|
||||
r[i] = av_clipf((1 - w1) * mid[i - 1] - side[i - 1] - w0 * p0, -1.0, 1.0);
|
||||
}
|
||||
|
||||
memcpy(s->prev_stereo_weights, s->stereo_weights, sizeof(s->stereo_weights));
|
||||
}
|
||||
|
||||
static void silk_flush_frame(SilkFrame *frame)
|
||||
{
|
||||
if (!frame->coded)
|
||||
return;
|
||||
|
||||
memset(frame->output, 0, sizeof(frame->output));
|
||||
memset(frame->lpc_history, 0, sizeof(frame->lpc_history));
|
||||
|
||||
memset(frame->lpc, 0, sizeof(frame->lpc));
|
||||
memset(frame->nlsf, 0, sizeof(frame->nlsf));
|
||||
|
||||
frame->log_gain = 0;
|
||||
|
||||
frame->primarylag = 0;
|
||||
frame->prev_voiced = 0;
|
||||
frame->coded = 0;
|
||||
}
|
||||
|
||||
int ff_silk_decode_superframe(SilkContext *s, OpusRangeCoder *rc,
|
||||
float *output[2],
|
||||
enum OpusBandwidth bandwidth,
|
||||
int coded_channels,
|
||||
int duration_ms)
|
||||
{
|
||||
int active[2][6], redundancy[2];
|
||||
int nb_frames, i, j;
|
||||
|
||||
if (bandwidth > OPUS_BANDWIDTH_WIDEBAND ||
|
||||
coded_channels > 2 || duration_ms > 60) {
|
||||
av_log(s->logctx, AV_LOG_ERROR, "Invalid parameters passed "
|
||||
"to the SILK decoder.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
nb_frames = 1 + (duration_ms > 20) + (duration_ms > 40);
|
||||
s->subframes = duration_ms / nb_frames / 5; // 5ms subframes
|
||||
s->sflength = 20 * (bandwidth + 2);
|
||||
s->flength = s->sflength * s->subframes;
|
||||
s->bandwidth = bandwidth;
|
||||
s->wb = bandwidth == OPUS_BANDWIDTH_WIDEBAND;
|
||||
|
||||
/* make sure to flush the side channel when switching from mono to stereo */
|
||||
if (coded_channels > s->prev_coded_channels)
|
||||
silk_flush_frame(&s->frame[1]);
|
||||
s->prev_coded_channels = coded_channels;
|
||||
|
||||
/* read the LP-layer header bits */
|
||||
for (i = 0; i < coded_channels; i++) {
|
||||
for (j = 0; j < nb_frames; j++)
|
||||
active[i][j] = ff_opus_rc_dec_log(rc, 1);
|
||||
|
||||
redundancy[i] = ff_opus_rc_dec_log(rc, 1);
|
||||
}
|
||||
|
||||
/* read the per-frame LBRR flags */
|
||||
for (i = 0; i < coded_channels; i++)
|
||||
if (redundancy[i] && duration_ms > 20) {
|
||||
redundancy[i] = ff_opus_rc_dec_cdf(rc, duration_ms == 40 ?
|
||||
ff_silk_model_lbrr_flags_40 : ff_silk_model_lbrr_flags_60);
|
||||
}
|
||||
|
||||
/* decode the LBRR frames */
|
||||
for (i = 0; i < nb_frames; i++) {
|
||||
for (j = 0; j < coded_channels; j++)
|
||||
if (redundancy[j] & (1 << i)) {
|
||||
int active1 = (j == 0 && !(redundancy[1] & (1 << i))) ? 0 : 1;
|
||||
silk_decode_frame(s, rc, i, j, coded_channels, 1, active1, 1);
|
||||
}
|
||||
|
||||
s->midonly = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_frames; i++) {
|
||||
for (j = 0; j < coded_channels && !s->midonly; j++) {
|
||||
int active1 = coded_channels > 1 ? active[1][i] : 0;
|
||||
silk_decode_frame(s, rc, i, j, coded_channels, active[j][i], active1, 0);
|
||||
}
|
||||
|
||||
/* reset the side channel if it is not coded */
|
||||
if (s->midonly && s->frame[1].coded)
|
||||
silk_flush_frame(&s->frame[1]);
|
||||
|
||||
if (coded_channels == 1 || s->output_channels == 1) {
|
||||
for (j = 0; j < s->output_channels; j++) {
|
||||
memcpy(output[j] + i * s->flength,
|
||||
s->frame[0].output + SILK_HISTORY - s->flength - 2,
|
||||
s->flength * sizeof(float));
|
||||
}
|
||||
} else {
|
||||
silk_unmix_ms(s, output[0] + i * s->flength, output[1] + i * s->flength);
|
||||
}
|
||||
|
||||
s->midonly = 0;
|
||||
}
|
||||
|
||||
return nb_frames * s->flength;
|
||||
}
|
||||
|
||||
void ff_silk_free(SilkContext **ps)
|
||||
{
|
||||
av_freep(ps);
|
||||
}
|
||||
|
||||
void ff_silk_flush(SilkContext *s)
|
||||
{
|
||||
silk_flush_frame(&s->frame[0]);
|
||||
silk_flush_frame(&s->frame[1]);
|
||||
|
||||
memset(s->prev_stereo_weights, 0, sizeof(s->prev_stereo_weights));
|
||||
}
|
||||
|
||||
int ff_silk_init(void *logctx, SilkContext **ps, int output_channels)
|
||||
{
|
||||
SilkContext *s;
|
||||
|
||||
if (output_channels != 1 && output_channels != 2) {
|
||||
av_log(logctx, AV_LOG_ERROR, "Invalid number of output channels: %d\n",
|
||||
output_channels);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
s = av_mallocz(sizeof(*s));
|
||||
if (!s)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
s->logctx = logctx;
|
||||
s->output_channels = output_channels;
|
||||
|
||||
ff_silk_flush(s);
|
||||
|
||||
*ps = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Opus Silk functions/definitions
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_SILK_H
|
||||
#define AVCODEC_OPUS_SILK_H
|
||||
|
||||
#include "opus.h"
|
||||
#include "rc.h"
|
||||
|
||||
#define SILK_HISTORY 322
|
||||
#define SILK_MAX_LPC 16
|
||||
|
||||
typedef struct SilkContext SilkContext;
|
||||
|
||||
int ff_silk_init(void *logctx, SilkContext **ps, int output_channels);
|
||||
void ff_silk_free(SilkContext **ps);
|
||||
void ff_silk_flush(SilkContext *s);
|
||||
|
||||
/**
|
||||
* Decode the LP layer of one Opus frame (which may correspond to several SILK
|
||||
* frames).
|
||||
*/
|
||||
int ff_silk_decode_superframe(SilkContext *s, OpusRangeCoder *rc,
|
||||
float *output[2],
|
||||
enum OpusBandwidth bandwidth, int coded_channels,
|
||||
int duration_ms);
|
||||
|
||||
#endif /* AVCODEC_OPUS_SILK_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew D'Addesio
|
||||
* Copyright (c) 2013-2014 Mozilla Corporation
|
||||
* Copyright (c) 2016 Rostislav Pehlivanov <atomnuker@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_OPUS_TAB_H
|
||||
#define AVCODEC_OPUS_TAB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/attributes_internal.h"
|
||||
|
||||
FF_VISIBILITY_PUSH_HIDDEN
|
||||
extern const uint8_t ff_celt_band_end[];
|
||||
|
||||
extern const uint8_t ff_opus_default_coupled_streams[];
|
||||
|
||||
extern const uint16_t ff_silk_model_lbrr_flags_40[];
|
||||
extern const uint16_t ff_silk_model_lbrr_flags_60[];
|
||||
|
||||
extern const uint16_t ff_silk_model_stereo_s1[];
|
||||
extern const uint16_t ff_silk_model_stereo_s2[];
|
||||
extern const uint16_t ff_silk_model_stereo_s3[];
|
||||
extern const uint16_t ff_silk_model_mid_only[];
|
||||
|
||||
extern const uint16_t ff_silk_model_frame_type_inactive[];
|
||||
extern const uint16_t ff_silk_model_frame_type_active[];
|
||||
|
||||
extern const uint16_t ff_silk_model_gain_highbits[3][9];
|
||||
extern const uint16_t ff_silk_model_gain_lowbits[];
|
||||
extern const uint16_t ff_silk_model_gain_delta[];
|
||||
|
||||
extern const uint16_t ff_silk_model_lsf_s1[2][2][33];
|
||||
extern const uint16_t ff_silk_model_lsf_s2[32][10];
|
||||
extern const uint16_t ff_silk_model_lsf_s2_ext[];
|
||||
extern const uint16_t ff_silk_model_lsf_interpolation_offset[];
|
||||
|
||||
extern const uint16_t ff_silk_model_pitch_highbits[];
|
||||
#define ff_silk_model_pitch_lowbits_nb ff_silk_model_lcg_seed
|
||||
extern const uint16_t ff_silk_model_pitch_lowbits_mb[];
|
||||
#define ff_silk_model_pitch_lowbits_wb ff_silk_model_gain_lowbits
|
||||
extern const uint16_t ff_silk_model_pitch_delta[];
|
||||
extern const uint16_t ff_silk_model_pitch_contour_nb10ms[];
|
||||
extern const uint16_t ff_silk_model_pitch_contour_nb20ms[];
|
||||
extern const uint16_t ff_silk_model_pitch_contour_mbwb10ms[];
|
||||
extern const uint16_t ff_silk_model_pitch_contour_mbwb20ms[];
|
||||
|
||||
extern const uint16_t ff_silk_model_ltp_filter[];
|
||||
extern const uint16_t ff_silk_model_ltp_filter0_sel[];
|
||||
extern const uint16_t ff_silk_model_ltp_filter1_sel[];
|
||||
extern const uint16_t ff_silk_model_ltp_filter2_sel[];
|
||||
extern const uint16_t ff_silk_model_ltp_scale_index[];
|
||||
|
||||
extern const uint16_t ff_silk_model_lcg_seed[];
|
||||
|
||||
extern const uint16_t ff_silk_model_exc_rate[2][10];
|
||||
|
||||
extern const uint16_t ff_silk_model_pulse_count[11][19];
|
||||
extern const uint16_t ff_silk_model_pulse_location[4][168];
|
||||
|
||||
extern const uint16_t ff_silk_model_excitation_lsb[];
|
||||
extern const uint16_t ff_silk_model_excitation_sign[3][2][7][3];
|
||||
|
||||
extern const int16_t ff_silk_stereo_weights[];
|
||||
|
||||
extern const uint8_t ff_silk_lsf_s2_model_sel_nbmb[32][10];
|
||||
extern const uint8_t ff_silk_lsf_s2_model_sel_wb[32][16];
|
||||
|
||||
extern const uint8_t ff_silk_lsf_pred_weights_nbmb[2][9];
|
||||
extern const uint8_t ff_silk_lsf_pred_weights_wb[2][15];
|
||||
|
||||
extern const uint8_t ff_silk_lsf_weight_sel_nbmb[32][9];
|
||||
extern const uint8_t ff_silk_lsf_weight_sel_wb[32][15];
|
||||
|
||||
extern const uint8_t ff_silk_lsf_codebook_nbmb[32][10];
|
||||
extern const uint8_t ff_silk_lsf_codebook_wb[32][16];
|
||||
|
||||
extern const uint16_t ff_silk_lsf_min_spacing_nbmb[];
|
||||
extern const uint16_t ff_silk_lsf_min_spacing_wb[];
|
||||
|
||||
extern const uint8_t ff_silk_lsf_ordering_nbmb[];
|
||||
extern const uint8_t ff_silk_lsf_ordering_wb[];
|
||||
|
||||
extern const int16_t ff_silk_cosine[];
|
||||
|
||||
extern const uint16_t ff_silk_pitch_scale[];
|
||||
extern const uint16_t ff_silk_pitch_min_lag[];
|
||||
extern const uint16_t ff_silk_pitch_max_lag[];
|
||||
|
||||
extern const int8_t ff_silk_pitch_offset_nb10ms[3][2];
|
||||
extern const int8_t ff_silk_pitch_offset_nb20ms[11][4];
|
||||
extern const int8_t ff_silk_pitch_offset_mbwb10ms[12][2];
|
||||
extern const int8_t ff_silk_pitch_offset_mbwb20ms[34][4];
|
||||
|
||||
extern const int8_t ff_silk_ltp_filter0_taps[8][5];
|
||||
extern const int8_t ff_silk_ltp_filter1_taps[16][5];
|
||||
extern const int8_t ff_silk_ltp_filter2_taps[32][5];
|
||||
|
||||
extern const uint16_t ff_silk_ltp_scale_factor[];
|
||||
|
||||
extern const uint8_t ff_silk_shell_blocks[3][2];
|
||||
|
||||
extern const uint8_t ff_silk_quant_offset[2][2];
|
||||
|
||||
extern const int ff_silk_stereo_interp_len[3];
|
||||
|
||||
extern const uint16_t ff_celt_model_tapset[];
|
||||
extern const uint16_t ff_celt_model_spread[];
|
||||
extern const uint16_t ff_celt_model_alloc_trim[];
|
||||
#define ff_celt_model_energy_small ff_celt_model_tapset
|
||||
|
||||
extern const uint8_t ff_celt_freq_bands[];
|
||||
extern const uint8_t ff_celt_freq_range[];
|
||||
extern const uint8_t ff_celt_log_freq_range[];
|
||||
|
||||
extern const int8_t ff_celt_tf_select[4][2][2][2];
|
||||
|
||||
extern const float ff_celt_mean_energy[];
|
||||
|
||||
extern const float ff_celt_alpha_coef[];
|
||||
extern const float ff_celt_beta_coef[];
|
||||
|
||||
extern const uint8_t ff_celt_coarse_energy_dist[4][2][42];
|
||||
|
||||
extern const uint8_t ff_celt_static_alloc[11][21];
|
||||
extern const uint8_t ff_celt_static_caps[4][2][21];
|
||||
|
||||
extern const uint8_t ff_celt_cache_bits[392];
|
||||
extern const int16_t ff_celt_cache_index[105];
|
||||
|
||||
extern const uint8_t ff_celt_log2_frac[];
|
||||
|
||||
extern const uint8_t ff_celt_bit_interleave[];
|
||||
extern const uint8_t ff_celt_bit_deinterleave[];
|
||||
|
||||
extern const uint8_t ff_celt_hadamard_order[];
|
||||
|
||||
extern const uint16_t ff_celt_qn_exp2[];
|
||||
|
||||
extern const float ff_celt_postfilter_taps[3][3];
|
||||
|
||||
extern const float ff_celt_window2[120];
|
||||
|
||||
extern const float ff_celt_window_padded[];
|
||||
static const float *const ff_celt_window = &ff_celt_window_padded[8];
|
||||
|
||||
extern const float ff_opus_deemph_weights[];
|
||||
|
||||
extern const uint32_t * const ff_celt_pvq_u_row[15];
|
||||
FF_VISIBILITY_POP_HIDDEN
|
||||
|
||||
#endif /* AVCODEC_OPUS_TAB_H */
|
||||
Reference in New Issue
Block a user