diff options
author | Rostislav Pehlivanov <atomnuker@gmail.com> | 2017-02-19 18:20:39 +0000 |
---|---|---|
committer | Rostislav Pehlivanov <atomnuker@gmail.com> | 2017-02-19 19:13:14 +0000 |
commit | 67fa02ed794f9505bd9c3584c14bfb61c895f5bc (patch) | |
tree | abe83b63829e7af14b209bfe090e260e8a06b6ed | |
parent | 4279613a2652cdf2bee564f4b7244567e5ba91ba (diff) | |
download | ffmpeg-67fa02ed794f9505bd9c3584c14bfb61c895f5bc.tar.gz |
opus_pvq: fix PVQ search for K < 5 and low Ns
If the PVQ search picked a place to increment/decrement on the y[]
vector which had no pulse then it would cause a desync since it would
change the sum in the wrong direction. Fix this by not considering
places without pulses as viable.
This makes the PVQ search slightly worse at K < 5 which isn't all that
common. Still, this is a workaround to prevent making broken files until
I can think of a better way of fixing it.
Also add an assertion, which can be removed or moved to assert1/2 once
the PVQ search is stable.
Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
-rw-r--r-- | libavcodec/opus_pvq.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/libavcodec/opus_pvq.c b/libavcodec/opus_pvq.c index 4197ccd3ad..5920ab0ed1 100644 --- a/libavcodec/opus_pvq.c +++ b/libavcodec/opus_pvq.c @@ -277,7 +277,7 @@ static inline int celt_compute_qn(int N, int b, int offset, int pulse_cap, } /* Convert the quantized vector to an index */ -static inline uint32_t celt_icwrsi(uint32_t N, const int *y) +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--) { @@ -285,6 +285,7 @@ static inline uint32_t celt_icwrsi(uint32_t N, const int *y) idx += CELT_PVQ_U(N - i, sum) + (y[i] < 0)*i_s; sum += FFABS(y[i]); } + av_assert0(sum == K); return idx; } @@ -376,7 +377,7 @@ static inline uint64_t celt_cwrsi(uint32_t N, uint32_t K, uint32_t i, int *y) 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, y), CELT_PVQ_V(N, 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) @@ -415,7 +416,8 @@ static void celt_pvq_search(float *X, int *y, int K, int N) float xy_new = xy_norm + 1*phase*FFABS(X[i]); float y_new = y_norm + 2*phase*FFABS(y[i]); xy_new = xy_new * xy_new; - if ((max_den*xy_new) > (y_new*max_num)) { + /* FIXME: the y[i] check makes the search slightly worse at Ks below 5 */ + if (y[i] && (max_den*xy_new) > (y_new*max_num)) { max_den = y_new; max_num = xy_new; max_idx = i; |