[FFmpeg-soc] [soc]: r3480 - mlp/mlpenc.c

ramiro subversion at mplayerhq.hu
Wed Aug 20 06:56:33 CEST 2008


Author: ramiro
Date: Wed Aug 20 06:56:32 2008
New Revision: 3480

Log:
Add dumb functions for rematrixing.

Modified:
   mlp/mlpenc.c

Modified: mlp/mlpenc.c
==============================================================================
--- mlp/mlpenc.c	(original)
+++ mlp/mlpenc.c	Wed Aug 20 06:56:32 2008
@@ -286,7 +286,7 @@ static uint8_t default_param_presence_fl
     uint8_t param_presence_flags = 0;
 
     param_presence_flags |= PARAM_BLOCKSIZE;
-/*  param_presence_flags |= PARAM_MATRIX; */
+    param_presence_flags |= PARAM_MATRIX;
 /*  param_presence_flags |= PARAM_OUTSHIFT; */
     param_presence_flags |= PARAM_QUANTSTEP;
     param_presence_flags |= PARAM_FIR;
@@ -306,6 +306,7 @@ static void default_decoding_params(MLPE
     for (substr = 0; substr < MAX_SUBSTREAMS; substr++) {
         DecodingParams *dp = &decoding_params[substr];
 
+        dp->num_primitive_matrices = ctx->avctx->channels - 1;
         dp->param_presence_flags = default_param_presence_flags();
     }
 }
@@ -391,6 +392,9 @@ static av_cold int mlp_encode_init(AVCod
     for (substr = 0; substr < ctx->num_substreams; substr++) {
         RestartHeader  *rh = &ctx->restart_header [substr];
 
+        /* TODO see if noisegen_seed is really worth it. */
+        rh->noisegen_seed      = 0;
+
         rh->min_channel        = 0;
         rh->max_channel        = avctx->channels - 1;
         rh->max_matrix_channel = 1;
@@ -480,6 +484,37 @@ static void write_filter_params(MLPEncod
     }
 }
 
+static void write_matrix_params(MLPEncodeContext *ctx, PutBitContext *pb,
+                                unsigned int substr)
+{
+    DecodingParams *dp = &ctx->decoding_params[substr];
+    unsigned int mat;
+
+    put_bits(pb, 4, dp->num_primitive_matrices);
+
+    for (mat = 1; mat <= dp->num_primitive_matrices; mat++) {
+        unsigned int channel;
+
+        put_bits(pb, 4, mat               ); /* matrix_out_ch */
+        put_bits(pb, 4, dp->frac_bits[mat]);
+        put_bits(pb, 1, 0                 ); /* lsb_bypass */
+
+        for (channel = 0; channel < ctx->num_channels; channel++) {
+            int32_t coeff = dp->matrix_coeff[mat][channel];
+
+            if (coeff) {
+                put_bits(pb, 1, 1);
+
+                coeff >>= 14 - dp->frac_bits[mat];
+
+                put_sbits(pb, dp->frac_bits[mat] + 2, coeff);
+            } else {
+                put_bits(pb, 1, 0);
+            }
+        }
+    }
+}
+
 /** Writes decoding parameters to the bitstream. These change very often,
  *  usually at almost every frame.
  */
@@ -510,12 +545,7 @@ static void write_decoding_params(MLPEnc
     if (dp->param_presence_flags & PARAM_MATRIX) {
         if (params_changed       & PARAM_MATRIX) {
             put_bits(pb, 1, 1);
-#if 1
-            put_bits(pb, 4, 0);
-#else
-            /* TODO no primitive matrices yet. */
-            put_bits(pb, 4, dp->num_primitive_matrices);
-#endif
+            write_matrix_params(ctx, pb, substr);
         } else {
             put_bits(pb, 1, 0);
         }
@@ -775,6 +805,117 @@ static int apply_filter(MLPEncodeContext
     return 0;
 }
 
+static void generate_2_noise_channels(MLPEncodeContext *ctx, unsigned int substr)
+{
+    int32_t *sample_buffer = ctx->sample_buffer + ctx->num_channels - 2;
+    RestartHeader *rh = &ctx->restart_header[substr];
+    unsigned int i;
+    uint32_t seed = rh->noisegen_seed;
+
+    for (i = 0; i < ctx->major_frame_size; i++) {
+        uint16_t seed_shr7 = seed >> 7;
+        *sample_buffer++ = ((int8_t)(seed >> 15)) << rh->noise_shift;
+        *sample_buffer++ = ((int8_t) seed_shr7)   << rh->noise_shift;
+
+        seed = (seed << 16) ^ seed_shr7 ^ (seed_shr7 << 5);
+
+        sample_buffer += ctx->num_channels - 2;
+    }
+
+    rh->noisegen_seed = seed & ((1 << 24)-1);
+}
+
+static int code_matrix_coeffs(MLPEncodeContext *ctx,
+                               unsigned int substr, unsigned int mat)
+{
+    DecodingParams *dp = &ctx->decoding_params[substr];
+    int32_t min = INT32_MAX, max = INT32_MIN;
+    int32_t coeff_mask = 0;
+    unsigned int channel;
+    unsigned int shift;
+    unsigned int bits;
+
+    /* No decorrelation for mono. */
+    if (ctx->num_channels - 2 == 1)
+        return 0;
+
+    for (channel = 0; channel < ctx->num_channels; channel++) {
+        int32_t coeff = dp->matrix_coeff[mat][channel];
+
+        if (coeff < min)
+            min = coeff;
+        if (coeff > max)
+            max = coeff;
+
+        coeff_mask |= coeff;
+    }
+
+    shift = FFMAX(0, FFMAX(number_sbits(min), number_sbits(max)) - 16);
+
+    if (shift) {
+#if 1
+        for (channel = 0; channel < ctx->num_channels; channel++)
+            dp->matrix_coeff[mat][channel] >>= shift;
+
+        coeff_mask >>= shift;
+#else
+        /* I can't get output_shift to work yet. */
+        return 0;
+#endif
+    }
+
+    for (bits = 0; bits < 14 && !(coeff_mask & (1<<bits)); bits++);
+
+    dp->frac_bits   [mat] = 14 - bits;
+    dp->output_shift[mat] = shift;
+
+    return ctx->num_channels - 3;
+}
+
+static void lossless_matrix_coeffs(MLPEncodeContext *ctx, unsigned int substr)
+{
+    DecodingParams *dp = &ctx->decoding_params[substr];
+
+    generate_2_noise_channels(ctx, substr);
+
+    /* TODO actual decorrelation. */
+
+    dp->matrix_coeff[1][0] =  1 << 14;
+    dp->matrix_coeff[1][1] = -1 << 14;
+    dp->matrix_coeff[1][2] =  0 << 14;
+    dp->matrix_coeff[1][3] =  0 << 14;
+
+    dp->num_primitive_matrices = code_matrix_coeffs(ctx, substr, 1);
+}
+
+static void rematrix_channels(MLPEncodeContext *ctx, unsigned int substr)
+{
+    DecodingParams *dp = &ctx->decoding_params[substr];
+    int32_t *sample_buffer = ctx->sample_buffer;
+    unsigned int mat, i, maxchan;
+
+    maxchan = ctx->num_channels;
+
+    for (mat = 1; mat <= dp->num_primitive_matrices; mat++) {
+        unsigned int msb_mask_bits = (ctx->avctx->sample_fmt == SAMPLE_FMT_S16 ? 8 : 0) - dp->output_shift[mat];
+        int32_t mask = MSB_MASK(msb_mask_bits);
+
+        sample_buffer = ctx->sample_buffer;
+        for (i = 0; i < ctx->major_frame_size; i++) {
+            unsigned int src_ch;
+            int64_t accum = 0;
+
+            for (src_ch = 0; src_ch < maxchan; src_ch++) {
+                int32_t sample = *(sample_buffer + src_ch);
+                accum += (int64_t) sample * dp->matrix_coeff[mat][src_ch];
+            }
+            sample_buffer[mat] = (accum >> 14) & mask;
+
+            sample_buffer += ctx->num_channels;
+        }
+    }
+}
+
 /** Min and max values that can be encoded with each codebook. The values for
  *  the third codebook take into account the fact that the sign shift for this
  *  codebook is outside the coded value, so it has one more bit of precision.
@@ -1395,6 +1536,8 @@ static int mlp_encode_frame(AVCodecConte
         ctx->next_major_frame_size = 0;
 
         for (substr = 0; substr < ctx->num_substreams; substr++) {
+            lossless_matrix_coeffs   (ctx, substr);
+            rematrix_channels        (ctx, substr);
             determine_quant_step_size(ctx, substr);
         }
 



More information about the FFmpeg-soc mailing list