]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/opusenc_psy.c
dashdec: Make use of frame rate specified in Representation
[ffmpeg] / libavcodec / opusenc_psy.c
index 1b108ecb873b61a63642f0c9b646f22927e8c7a4..8aded2140de152c2c55354996b787ef27e2a3dbb 100644 (file)
 #include "mdct15.h"
 #include "libavutil/qsort.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)
 {
@@ -69,7 +119,7 @@ static void step_collect_psy_metrics(OpusPsyContext *s, int index)
 
             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);
+                dist_dev += (avg_c_s - c_s)*(avg_c_s - c_s);
             }
 
             st->tone[ch][i] += sqrtf(dist_dev);
@@ -316,11 +366,11 @@ static int bands_dist(OpusPsyContext *s, CeltFrame *f, float *total_dist)
     OpusRangeCoder dump;
 
     ff_opus_rc_enc_init(&dump);
-    ff_celt_enc_bitalloc(&dump, f);
+    ff_celt_bitalloc(f, &dump, 1);
 
     for (i = 0; i < CELT_MAX_BANDS; i++) {
         float bits = 0.0f;
-        float dist = f->pvq->band_cost(f->pvq, f, &dump, i, &bits, s->lambda);
+        float dist = pvq_band_cost(f->pvq, f, &dump, i, &bits, s->lambda);
         tdist += dist;
     }
 
@@ -333,6 +383,10 @@ static void celt_search_for_dual_stereo(OpusPsyContext *s, CeltFrame *f)
 {
     float td1, td2;
     f->dual_stereo = 0;
+
+    if (s->avctx->channels < 2)
+        return;
+
     bands_dist(s, f, &td1);
     f->dual_stereo = 1;
     bands_dist(s, f, &td2);
@@ -346,6 +400,9 @@ static void celt_search_for_intensity(OpusPsyContext *s, CeltFrame *f)
     int i, best_band = CELT_MAX_BANDS - 1;
     float dist, best_dist = FLT_MAX;
 
+    if (s->avctx->channels < 2)
+        return;
+
     /* TODO: fix, make some heuristic up here using the lambda value */
     float end_band = 0;