[soc]: r5419 - als/alsdec.c
Author: thilo.borgmann Date: Tue Oct 20 15:00:40 2009 New Revision: 5419 Log: Splits reading of block data and decoding of block data. Introduces ALSBlockData struct. Modified: als/alsdec.c Modified: als/alsdec.c ============================================================================== --- als/alsdec.c Mon Oct 19 11:39:30 2009 (r5418) +++ als/alsdec.c Tue Oct 20 15:00:40 2009 (r5419) @@ -88,6 +88,26 @@ typedef struct { } ALSDecContext; +typedef struct { + unsigned int block_length; ///< number of samples within the block + unsigned int ra_block; ///< if true, this is a random access block + int const_block; ///< if true, this is a constant value block + int32_t const_val; ///< the sample value of a constant block + int js_blocks; ///< true if this block contains a difference signal + unsigned int shift_lsbs; ///< shift of values for this block + unsigned int opt_order; ///< prediction order of this block + int store_prev_samples;///< if true, carryover samples have to be stored + int use_ltp; ///< if true, long-term prediction is used + int ltp_lag; ///< lag value for long-term prediction + int ltp_gain[5]; ///< gain values for ltp 5-tap filter + int32_t *quant_cof; ///< quantized parcor coefficients + int32_t *lpc_cof; ///< coefficients of the direct form prediction + int32_t *raw_samples; ///< decoded raw samples / residuals for this block + int32_t *prev_raw_samples; ///< contains unshifted raw samples from the previous block + int32_t *raw_other; ///< decoded raw samples of the other channel of a channel pair +} ALSBlockData; + + static av_cold void dprint_specific_config(ALSDecContext *ctx) { #ifdef DEBUG @@ -424,38 +444,44 @@ static void get_block_sizes(ALSDecContex /** Reads the block data for a constant block */ -static void read_const_block(ALSDecContext *ctx, int32_t *raw_samples, - unsigned int block_length, unsigned int *js_blocks) +static void read_const_block_data(ALSDecContext *ctx, ALSBlockData *bd) { ALSSpecificConfig *sconf = &ctx->sconf; AVCodecContext *avctx = ctx->avctx; GetBitContext *gb = &ctx->gb; - int32_t const_val = 0; - unsigned int const_block, k; - const_block = get_bits1(gb); // 1 = constant value, 0 = zero block (silence) - *js_blocks = get_bits1(gb); + bd->const_val = 0; + bd->const_block = get_bits1(gb); // 1 = constant value, 0 = zero block (silence) + bd->js_blocks = get_bits1(gb); // skip 5 reserved bits skip_bits(gb, 5); - if (const_block) { + if (bd->const_block) { unsigned int const_val_bits = sconf->floating ? 24 : avctx->bits_per_raw_sample; - const_val = get_sbits_long(gb, const_val_bits); + bd->const_val = get_sbits_long(gb, const_val_bits); } + // ensure constant block decoding by reusing this field + bd->const_block = 1; +} + + +/** Decodes the block data for a constant block + */ +static void decode_const_block_data(ALSDecContext *ctx, ALSBlockData *bd) +{ + int smp; + // write raw samples into buffer - for (k = 0; k < block_length; k++) - raw_samples[k] = const_val; + for (smp = 0; smp < bd->block_length; smp++) + bd->raw_samples[smp] = bd->const_val; } /** Reads the block data for a non-constant block */ -static int read_var_block(ALSDecContext *ctx, unsigned int ra_block, - int32_t *raw_samples, unsigned int block_length, - unsigned int *js_blocks, int32_t *raw_other, - unsigned int *shift_lsbs) +static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) { ALSSpecificConfig *sconf = &ctx->sconf; AVCodecContext *avctx = ctx->avctx; @@ -463,18 +489,14 @@ static int read_var_block(ALSDecContext unsigned int k; unsigned int s[8]; unsigned int sub_blocks, log2_sub_blocks, sb_length; - unsigned int opt_order = 1; - int32_t *quant_cof = ctx->quant_cof; - int32_t *lpc_cof = ctx->lpc_cof; unsigned int start = 0; - int smp = 0; - int sb, store_prev_samples; - int64_t y; - int use_ltp = 0; - int ltp_lag = 0; - int ltp_gain[5]; + int sb; - *js_blocks = get_bits1(gb); + // ensure variable block decoding by reusing this field + bd->const_block = 0; + + bd->opt_order = 1; + bd->js_blocks = get_bits1(gb); // determine the number of subblocks for entropy decoding if (!sconf->bgmc && !sconf->sb_part) { @@ -490,13 +512,13 @@ static int read_var_block(ALSDecContext // do not continue in case of a damaged stream since // block_length must be evenly divisible by sub_blocks - if (block_length & (sub_blocks - 1)) { + if (bd->block_length & (sub_blocks - 1)) { av_log(avctx, AV_LOG_WARNING, "Block length is not evenly divisible by the number of subblocks.\n"); return -1; } - sb_length = block_length >> log2_sub_blocks; + sb_length = bd->block_length >> log2_sub_blocks; if (sconf->bgmc) { @@ -508,119 +530,134 @@ static int read_var_block(ALSDecContext } if (get_bits1(gb)) - *shift_lsbs = get_bits(gb, 4) + 1; - - store_prev_samples = (*js_blocks && raw_other) || *shift_lsbs; + bd->shift_lsbs = get_bits(gb, 4) + 1; + bd->store_prev_samples = (bd->js_blocks && bd->raw_other) || + bd->shift_lsbs; if (!sconf->rlslms) { if (sconf->adapt_order) { - int opt_order_length = av_ceil_log2(av_clip((block_length >> 3) - 1, - 2, sconf->max_order + 1)); - opt_order = get_bits(gb, opt_order_length); + int opt_order_length = av_ceil_log2(av_clip((bd->block_length >> 3) - 1, + 2, sconf->max_order + 1)); + bd->opt_order = get_bits(gb, opt_order_length); } else { - opt_order = sconf->max_order; + bd->opt_order = sconf->max_order; } - if (opt_order) { + if (bd->opt_order) { int add_base; if (sconf->coef_table == 3) { add_base = 0x7F; // read coefficient 0 - quant_cof[0] = parcor_scaled_values[get_bits(gb, 7)]; - quant_cof[0] *= 32; + bd->quant_cof[0] = parcor_scaled_values[get_bits(gb, 7)]; + bd->quant_cof[0] *= 32; // read coefficient 1 - quant_cof[1] = -parcor_scaled_values[get_bits(gb, 7)]; - quant_cof[0] *= 32; + bd->quant_cof[1] = -parcor_scaled_values[get_bits(gb, 7)]; + bd->quant_cof[0] *= 32; // read coefficients 2 to opt_order - for (k = 2; k < opt_order; k++) - quant_cof[k] = get_bits(gb, 7); + for (k = 2; k < bd->opt_order; k++) + bd->quant_cof[k] = get_bits(gb, 7); } else { int k_max; add_base = 1; // read coefficient 0 to 19 - k_max = FFMIN(opt_order, 20); + k_max = FFMIN(bd->opt_order, 20); for (k = 0; k < k_max; k++) { int rice_param = parcor_rice_table[sconf->coef_table][k][1]; int offset = parcor_rice_table[sconf->coef_table][k][0]; - quant_cof[k] = decode_rice(gb, rice_param) + offset; + bd->quant_cof[k] = decode_rice(gb, rice_param) + offset; } // read coefficients 20 to 126 - k_max = FFMIN(opt_order, 127); + k_max = FFMIN(bd->opt_order, 127); for (; k < k_max; k++) - quant_cof[k] = decode_rice(gb, 2) + (k & 1); + bd->quant_cof[k] = decode_rice(gb, 2) + (k & 1); // read coefficients 127 to opt_order - for (; k < opt_order; k++) - quant_cof[k] = decode_rice(gb, 1); + for (; k < bd->opt_order; k++) + bd->quant_cof[k] = decode_rice(gb, 1); - quant_cof[0] = parcor_scaled_values[quant_cof[0] + 64]; - quant_cof[0] *= 32; - quant_cof[1] = -parcor_scaled_values[quant_cof[1] + 64]; - quant_cof[1] *= 32; + bd->quant_cof[0] = parcor_scaled_values[bd->quant_cof[0] + 64]; + bd->quant_cof[0] *= 32; + bd->quant_cof[1] = -parcor_scaled_values[bd->quant_cof[1] + 64]; + bd->quant_cof[1] *= 32; } - for (k = 2; k < opt_order; k++) - quant_cof[k] = (quant_cof[k] << 14) + (add_base << 13); + for (k = 2; k < bd->opt_order; k++) + bd->quant_cof[k] = (bd->quant_cof[k] << 14) + (add_base << 13); } } // read LTP gain and lag values if (sconf->long_term_prediction) { - use_ltp = get_bits1(gb); + bd->use_ltp = get_bits1(gb); - if (use_ltp) { - ltp_gain[0] = decode_rice(gb, 1) << 3; - ltp_gain[1] = decode_rice(gb, 2) << 3; + if (bd->use_ltp) { + bd->ltp_gain[0] = decode_rice(gb, 1) << 3; + bd->ltp_gain[1] = decode_rice(gb, 2) << 3; - ltp_gain[2] = get_unary(gb, 0, 4); - ltp_gain[2] <<= 2; - ltp_gain[2] += get_bits(gb, 2); - ltp_gain[2] = ltp_gain_values[ltp_gain[2]]; + bd->ltp_gain[2] = get_unary(gb, 0, 4); + bd->ltp_gain[2] <<= 2; + bd->ltp_gain[2] += get_bits(gb, 2); + bd->ltp_gain[2] = ltp_gain_values[bd->ltp_gain[2]]; - ltp_gain[3] = decode_rice(gb, 2) << 3; - ltp_gain[4] = decode_rice(gb, 1) << 3; + bd->ltp_gain[3] = decode_rice(gb, 2) << 3; + bd->ltp_gain[4] = decode_rice(gb, 1) << 3; - ltp_lag = get_bits(gb, ctx->ltp_lag_length); - ltp_lag += FFMAX(4, opt_order + 1); + bd->ltp_lag = get_bits(gb, ctx->ltp_lag_length); + bd->ltp_lag += FFMAX(4, bd->opt_order + 1); } } // read first value and residuals in case of a random access block - if (ra_block) { - if (opt_order) - raw_samples[0] = decode_rice(gb, avctx->bits_per_raw_sample - 4); - if (opt_order > 1) - raw_samples[1] = decode_rice(gb, s[0] + 3); - if (opt_order > 2) - raw_samples[2] = decode_rice(gb, s[0] + 1); + if (bd->ra_block) { + if (bd->opt_order) + bd->raw_samples[0] = decode_rice(gb, avctx->bits_per_raw_sample - 4); + if (bd->opt_order > 1) + bd->raw_samples[1] = decode_rice(gb, s[0] + 3); + if (bd->opt_order > 2) + bd->raw_samples[2] = decode_rice(gb, s[0] + 1); - start = FFMIN(opt_order, 3); + start = FFMIN(bd->opt_order, 3); } // read all residuals if (sconf->bgmc) { // TODO: BGMC mode } else { - int32_t *current_res = raw_samples + start; + int32_t *current_res = bd->raw_samples + start; for (sb = 0; sb < sub_blocks; sb++, start = 0) for (; start < sb_length; start++) *current_res++ = decode_rice(gb, s[sb]); - } + } + + return 0; +} + + +/** Decodes the block data for a non-constant block + */ +static int decode_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) +{ + ALSSpecificConfig *sconf = &ctx->sconf; + unsigned int block_length = bd->block_length; + unsigned int smp = 0; + unsigned int k; + int sb; + int64_t y; // reverse long-term prediction - if (use_ltp) { + if (bd->use_ltp) { int ltp_smp; - for (ltp_smp = FFMAX(ltp_lag - 2, 0); ltp_smp < block_length; ltp_smp++) { - int center = ltp_smp - ltp_lag; + for (ltp_smp = FFMAX(bd->ltp_lag - 2, 0); ltp_smp < block_length; ltp_smp++) { + int center = ltp_smp - bd->ltp_lag; int begin = FFMAX(0, center - 2); int end = center + 3; int tab = 5 - (end - begin); @@ -629,68 +666,68 @@ static int read_var_block(ALSDecContext y = 1 << 6; for (base = begin; base < end; base++, tab++) - y += MUL64(ltp_gain[tab], raw_samples[base]); + y += MUL64(bd->ltp_gain[tab], bd->raw_samples[base]); - raw_samples[ltp_smp] += y >> 7; + bd->raw_samples[ltp_smp] += y >> 7; } } // reconstruct all samples from residuals - if (ra_block) { - for (smp = 0; smp < opt_order; smp++) { + if (bd->ra_block) { + for (smp = 0; smp < bd->opt_order; smp++) { y = 1 << 19; for (sb = 0; sb < smp; sb++) - y += MUL64(lpc_cof[sb],raw_samples[smp - (sb + 1)]); + y += MUL64(bd->lpc_cof[sb], bd->raw_samples[smp - (sb + 1)]); - raw_samples[smp] -= y >> 20; - parcor_to_lpc(smp, quant_cof, lpc_cof); + bd->raw_samples[smp] -= y >> 20; + parcor_to_lpc(smp, bd->quant_cof, bd->lpc_cof); } } else { - for (k = 0; k < opt_order; k++) - parcor_to_lpc(k, quant_cof, lpc_cof); + for (k = 0; k < bd->opt_order; k++) + parcor_to_lpc(k, bd->quant_cof, bd->lpc_cof); // store previous samples in case that they have to be altered - if (store_prev_samples) - memcpy(ctx->prev_raw_samples, raw_samples - sconf->max_order, - sizeof(*ctx->prev_raw_samples) * sconf->max_order); + if (bd->store_prev_samples) + memcpy(bd->prev_raw_samples, bd->raw_samples - sconf->max_order, + sizeof(*bd->prev_raw_samples) * sconf->max_order); // reconstruct difference signal for prediction (joint-stereo) - if (*js_blocks && raw_other) { + if (bd->js_blocks && bd->raw_other) { int32_t *left, *right; - if (raw_other > raw_samples) { // D = R - L - left = raw_samples; - right = raw_other; + if (bd->raw_other > bd->raw_samples) { // D = R - L + left = bd->raw_samples; + right = bd->raw_other; } else { // D = R - L - left = raw_other; - right = raw_samples; + left = bd->raw_other; + right = bd->raw_samples; } for (sb = -1; sb >= -sconf->max_order; sb--) - raw_samples[sb] = right[sb] - left[sb]; + bd->raw_samples[sb] = right[sb] - left[sb]; } // reconstruct shifted signal - if (*shift_lsbs) + if (bd->shift_lsbs) for (sb = -1; sb >= -sconf->max_order; sb--) - raw_samples[sb] >>= *shift_lsbs; + bd->raw_samples[sb] >>= bd->shift_lsbs; } // reconstruct raw samples - for (; smp < block_length; smp++) { + for (; smp < bd->block_length; smp++) { y = 1 << 19; - for (sb = 0; sb < opt_order; sb++) - y += MUL64(lpc_cof[sb],raw_samples[smp - (sb + 1)]); + for (sb = 0; sb < bd->opt_order; sb++) + y += MUL64(bd->lpc_cof[sb], bd->raw_samples[smp - (sb + 1)]); - raw_samples[smp] -= y >> 20; + bd->raw_samples[smp] -= y >> 20; } // restore previous samples in case that they have been altered - if (store_prev_samples) - memcpy(raw_samples - sconf->max_order, ctx->prev_raw_samples, - sizeof(*raw_samples) * sconf->max_order); + if (bd->store_prev_samples) + memcpy(bd->raw_samples - sconf->max_order, bd->prev_raw_samples, + sizeof(*bd->raw_samples) * sconf->max_order); return 0; } @@ -698,32 +735,42 @@ static int read_var_block(ALSDecContext /** Reads the block data. */ -static int read_block_data(ALSDecContext *ctx, unsigned int ra_block, - int32_t *raw_samples, unsigned int block_length, - unsigned int *js_blocks, int32_t *raw_other) +static int read_block(ALSDecContext *ctx, ALSBlockData *bd) +{ + GetBitContext *gb = &ctx->gb; + + // read block type flag and read the samples accordingly + if (get_bits1(gb)) + read_var_block_data(ctx, bd); + else + read_const_block_data(ctx, bd); + + return 0; +} + + +/** Decodes the block data. + */ +static int decode_block(ALSDecContext *ctx, ALSBlockData *bd) { ALSSpecificConfig *sconf = &ctx->sconf; GetBitContext *gb = &ctx->gb; - unsigned int shift_lsbs = 0; - unsigned int k; + unsigned int smp; // read block type flag and read the samples accordingly - if (get_bits1(gb)) { - if (read_var_block(ctx, ra_block, raw_samples, block_length, js_blocks, - raw_other, &shift_lsbs)) - return -1; - } else { - read_const_block(ctx, raw_samples, block_length, js_blocks); - } + if (bd->const_block) + decode_const_block_data(ctx, bd); + else if (decode_var_block_data(ctx, bd)) + return -1; // TODO: read RLSLMS extension data if (!sconf->mc_coding || ctx->js_switch) align_get_bits(gb); - if (shift_lsbs) - for (k = 0; k < block_length; k++) - raw_samples[k] <<= shift_lsbs; + if (bd->shift_lsbs) + for (smp = 0; smp < bd->block_length; smp++) + bd->raw_samples[smp] <<= bd->shift_lsbs; return 0; } @@ -750,21 +797,34 @@ static int decode_blocks_ind(ALSDecConte unsigned int c, const unsigned int *div_blocks, unsigned int *js_blocks) { - int32_t *raw_sample; unsigned int b; - raw_sample = ctx->raw_samples[c]; + ALSBlockData bd; + + memset(&bd, 0, sizeof(ALSBlockData)); + + bd.ra_block = ra_frame; + bd.quant_cof = ctx->quant_cof; + bd.lpc_cof = ctx->lpc_cof; + bd.prev_raw_samples = ctx->prev_raw_samples; + bd.raw_samples = ctx->raw_samples[c]; + for (b = 0; b < ctx->num_blocks; b++) { - if (read_block_data(ctx, ra_frame, raw_sample, - div_blocks[b], &js_blocks[0], NULL)) { - // damaged block, write zero for the rest of the frame - zero_remaining(b, ctx->num_blocks, div_blocks, raw_sample); + bd.shift_lsbs = 0; + bd.block_length = div_blocks[b]; + + if (read_block(ctx, &bd) || + decode_block(ctx, &bd)) { + zero_remaining(b, ctx->num_blocks, div_blocks, bd.raw_samples); return -1; - } - raw_sample += div_blocks[b]; - ra_frame = 0; + } + + bd.raw_samples += div_blocks[b]; + bd.ra_block = 0; } + *js_blocks = bd.js_blocks; + return 0; } @@ -777,39 +837,62 @@ static int decode_blocks(ALSDecContext * { ALSSpecificConfig *sconf = &ctx->sconf; unsigned int offset = 0; - int32_t *raw_samples_R; - int32_t *raw_samples_L; unsigned int b; + ALSBlockData bd[2]; + + memset(bd, 0, 2 * sizeof(ALSBlockData)); + + bd[0].ra_block = ra_frame; + bd[0].quant_cof = ctx->quant_cof; + bd[0].lpc_cof = ctx->lpc_cof; + bd[0].prev_raw_samples = ctx->prev_raw_samples; + bd[0].js_blocks = *js_blocks; + + bd[1].ra_block = ra_frame; + bd[1].quant_cof = ctx->quant_cof; + bd[1].lpc_cof = ctx->lpc_cof; + bd[1].prev_raw_samples = ctx->prev_raw_samples; + bd[1].js_blocks = *(js_blocks + 1); // decode all blocks for (b = 0; b < ctx->num_blocks; b++) { unsigned int s; - raw_samples_L = ctx->raw_samples[c ] + offset; - raw_samples_R = ctx->raw_samples[c + 1] + offset; - if (read_block_data(ctx, ra_frame, raw_samples_L, div_blocks[b], - &js_blocks[0], raw_samples_R) || - read_block_data(ctx, ra_frame, raw_samples_R, div_blocks[b], - &js_blocks[1], raw_samples_L)) { + + bd[0].shift_lsbs = 0; + bd[1].shift_lsbs = 0; + + bd[0].block_length = div_blocks[b]; + bd[1].block_length = div_blocks[b]; + + bd[0].raw_samples = ctx->raw_samples[c ] + offset; + bd[1].raw_samples = ctx->raw_samples[c + 1] + offset; + + bd[0].raw_other = bd[1].raw_samples; + bd[1].raw_other = bd[0].raw_samples; + + if (read_block(ctx, &bd[0]) || decode_block(ctx, &bd[0]) || + read_block(ctx, &bd[1]) || decode_block(ctx, &bd[1])) { // damaged block, write zero for the rest of the frame - zero_remaining(b, ctx->num_blocks, div_blocks, raw_samples_L); - zero_remaining(b, ctx->num_blocks, div_blocks, raw_samples_R); + zero_remaining(b, ctx->num_blocks, div_blocks, bd[0].raw_samples); + zero_remaining(b, ctx->num_blocks, div_blocks, bd[1].raw_samples); return -1; } // reconstruct joint-stereo blocks - if (js_blocks[0]) { - if (js_blocks[1]) + if (bd[0].js_blocks) { + if (bd[1].js_blocks) av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel pair!\n"); for (s = 0; s < div_blocks[b]; s++) - raw_samples_L[s] = raw_samples_R[s] - raw_samples_L[s]; - } else if (js_blocks[1]) { + bd[0].raw_samples[s] = bd[1].raw_samples[s] - bd[0].raw_samples[s]; + } else if (bd[1].js_blocks) { for (s = 0; s < div_blocks[b]; s++) - raw_samples_R[s] = raw_samples_R[s] + raw_samples_L[s]; + bd[1].raw_samples[s] = bd[1].raw_samples[s] + bd[0].raw_samples[s]; } offset += div_blocks[b]; - ra_frame = 0; + bd[0].ra_block = 0; + bd[1].ra_block = 0; } // store carryover raw samples,
On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote:
Author: thilo.borgmann Date: Tue Oct 20 15:00:40 2009 New Revision: 5419
Log: Splits reading of block data and decoding of block data. Introduces ALSBlockData struct.
You are missing the "why" part, that should be explained in the commit message also this needs a benchmark as there are many additional dereferences added [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
... defining _GNU_SOURCE... For the love of all that is holy, and some that is not, don't do that. -- Luca & Mans
Michael Niedermayer schrieb:
On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote:
Author: thilo.borgmann Date: Tue Oct 20 15:00:40 2009 New Revision: 5419
Log: Splits reading of block data and decoding of block data. Introduces ALSBlockData struct.
You are missing the "why" part, that should be explained in the commit message
Yes, sorry.
also this needs a benchmark as there are many additional dereferences added
It is a necessary evil to support MCC. If it would be faster the "old" way for non-MCC files, would this reason to have both, a split read & decode function pair and an all-in-one function? -Thilo
On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote:
Author: thilo.borgmann Date: Tue Oct 20 15:00:40 2009 New Revision: 5419
Log: Splits reading of block data and decoding of block data. Introduces ALSBlockData struct.
You are missing the "why" part, that should be explained in the commit message
Yes, sorry.
also this needs a benchmark as there are many additional dereferences added
It is a necessary evil to support MCC. If it would be faster the "old" way for non-MCC files, would this reason to have both, a split read & decode function pair and an all-in-one function?
I think a benchmark is usefull to judge if we should spend time thinking about alternatives to the many dereferences or not [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB In fact, the RIAA has been known to suggest that students drop out of college or go to community college in order to be able to afford settlements. -- The RIAA
Michael Niedermayer schrieb:
On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote:
Author: thilo.borgmann Date: Tue Oct 20 15:00:40 2009 New Revision: 5419
Log: Splits reading of block data and decoding of block data. Introduces ALSBlockData struct. You are missing the "why" part, that should be explained in the commit message Yes, sorry.
also this needs a benchmark as there are many additional dereferences added It is a necessary evil to support MCC. If it would be faster the "old" way for non-MCC files, would this reason to have both, a split read & decode function pair and an all-in-one function?
I think a benchmark is usefull to judge if we should spend time thinking about alternatives to the many dereferences or not
The combined (old) function: 848450 dezicycles in combined, 1 runs, 0 skips 436625 dezicycles in combined, 2 runs, 0 skips 422562 dezicycles in combined, 4 runs, 0 skips 251822 dezicycles in combined, 8 runs, 0 skips 275631 dezicycles in combined, 16 runs, 0 skips 244726 dezicycles in combined, 32 runs, 0 skips 206217 dezicycles in combined, 64 runs, 0 skips 179422 dezicycles in combined, 119 runs, 9 skips 179422 dezicycles in combined, 119 runs, 137 skips The separate (new) functions: 984100 dezicycles in separate, 1 runs, 0 skips 499555 dezicycles in separate, 2 runs, 0 skips 534420 dezicycles in separate, 4 runs, 0 skips 369905 dezicycles in separate, 8 runs, 0 skips 340817 dezicycles in separate, 16 runs, 0 skips 280026 dezicycles in separate, 32 runs, 0 skips 263883 dezicycles in separate, 64 runs, 0 skips 231872 dezicycles in separate, 119 runs, 9 skips 231872 dezicycles in separate, 119 runs, 137 skips This is a 30% difference which makes me think to try these alternatives. What comes into my mind would be to use local copies, thus dereferencing the field of *bd just twice. One at the top and one at the bottom of the function. Anything else? -Thilo
Thilo Borgmann schrieb:
Michael Niedermayer schrieb:
On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote:
Author: thilo.borgmann Date: Tue Oct 20 15:00:40 2009 New Revision: 5419
Log: Splits reading of block data and decoding of block data. Introduces ALSBlockData struct. You are missing the "why" part, that should be explained in the commit message Yes, sorry.
also this needs a benchmark as there are many additional dereferences added It is a necessary evil to support MCC. If it would be faster the "old" way for non-MCC files, would this reason to have both, a split read & decode function pair and an all-in-one function? I think a benchmark is usefull to judge if we should spend time thinking about alternatives to the many dereferences or not
The combined (old) function:
848450 dezicycles in combined, 1 runs, 0 skips 436625 dezicycles in combined, 2 runs, 0 skips 422562 dezicycles in combined, 4 runs, 0 skips 251822 dezicycles in combined, 8 runs, 0 skips 275631 dezicycles in combined, 16 runs, 0 skips 244726 dezicycles in combined, 32 runs, 0 skips 206217 dezicycles in combined, 64 runs, 0 skips 179422 dezicycles in combined, 119 runs, 9 skips 179422 dezicycles in combined, 119 runs, 137 skips
The separate (new) functions:
984100 dezicycles in separate, 1 runs, 0 skips 499555 dezicycles in separate, 2 runs, 0 skips 534420 dezicycles in separate, 4 runs, 0 skips 369905 dezicycles in separate, 8 runs, 0 skips 340817 dezicycles in separate, 16 runs, 0 skips 280026 dezicycles in separate, 32 runs, 0 skips 263883 dezicycles in separate, 64 runs, 0 skips 231872 dezicycles in separate, 119 runs, 9 skips 231872 dezicycles in separate, 119 runs, 137 skips
This is a 30% difference which makes me think to try these alternatives.
What comes into my mind would be to use local copies, thus dereferencing the field of *bd just twice. One at the top and one at the bottom of the function.
I tested using local copies instead of dereferencing: 10823450 dezicycles in local copies, 1 runs, 0 skips 6122845 dezicycles in local copies, 2 runs, 0 skips 4420565 dezicycles in local copies, 4 runs, 0 skips 3557323 dezicycles in local copies, 8 runs, 0 skips 2553006 dezicycles in local copies, 16 runs, 0 skips 2554690 dezicycles in local copies, 32 runs, 0 skips 2424406 dezicycles in local copies, 64 runs, 0 skips 2535575 dezicycles in local copies, 128 runs, 0 skips 2242664 dezicycles in local copies, 256 runs, 0 skips 69085900 dezicycles in dereferences, 1 runs, 0 skips 35455330 dezicycles in dereferences, 2 runs, 0 skips 19061607 dezicycles in dereferences, 4 runs, 0 skips 10732197 dezicycles in dereferences, 8 runs, 0 skips 6036062 dezicycles in dereferences, 16 runs, 0 skips 3893601 dezicycles in dereferences, 32 runs, 0 skips 3105304 dezicycles in dereferences, 64 runs, 0 skips 2732319 dezicycles in dereferences, 128 runs, 0 skips 2333672 dezicycles in dereferences, 256 runs, 0 skips That's a 4% gain so I think local copies don't pay off... Other alternatives? -Thilo
On Thu, Oct 22, 2009 at 11:29:55AM +0200, Thilo Borgmann wrote:
Thilo Borgmann schrieb:
Michael Niedermayer schrieb:
On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote:
Author: thilo.borgmann Date: Tue Oct 20 15:00:40 2009 New Revision: 5419
Log: Splits reading of block data and decoding of block data. Introduces ALSBlockData struct. You are missing the "why" part, that should be explained in the commit message Yes, sorry.
also this needs a benchmark as there are many additional dereferences added It is a necessary evil to support MCC. If it would be faster the "old" way for non-MCC files, would this reason to have both, a split read & decode function pair and an all-in-one function? I think a benchmark is usefull to judge if we should spend time thinking about alternatives to the many dereferences or not [...] This is a 30% difference which makes me think to try these alternatives.
What comes into my mind would be to use local copies, thus dereferencing the field of *bd just twice. One at the top and one at the bottom of the function.
I tested using local copies instead of dereferencing: [...] That's a 4% gain so I think local copies don't pay off...
Other alternatives?
i would first confirm that gcc did not do something stupid about inlining. Or more precissely not inlining some random unrelated function after the file got bigger ... [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB The bravest are surely those who have the clearest vision of what is before them, glory and danger alike, and yet notwithstanding go out to meet it. -- Thucydides
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 11:29:55AM +0200, Thilo Borgmann wrote:
Thilo Borgmann schrieb:
Michael Niedermayer schrieb:
On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote: > Author: thilo.borgmann > Date: Tue Oct 20 15:00:40 2009 > New Revision: 5419 > > Log: > Splits reading of block data and decoding of block data. > Introduces ALSBlockData struct. You are missing the "why" part, that should be explained in the commit message Yes, sorry.
also this needs a benchmark as there are many additional dereferences added It is a necessary evil to support MCC. If it would be faster the "old" way for non-MCC files, would this reason to have both, a split read & decode function pair and an all-in-one function? I think a benchmark is usefull to judge if we should spend time thinking about alternatives to the many dereferences or not [...] This is a 30% difference which makes me think to try these alternatives.
What comes into my mind would be to use local copies, thus dereferencing the field of *bd just twice. One at the top and one at the bottom of the function.
I tested using local copies instead of dereferencing: [...] That's a 4% gain so I think local copies don't pay off...
Other alternatives?
i would first confirm that gcc did not do something stupid about inlining. Or more precissely not inlining some random unrelated function after the file got bigger ...
How to do that?
On Thu, Oct 22, 2009 at 01:32:15PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 11:29:55AM +0200, Thilo Borgmann wrote:
Thilo Borgmann schrieb:
Michael Niedermayer schrieb:
On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb: > On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote: >> Author: thilo.borgmann >> Date: Tue Oct 20 15:00:40 2009 >> New Revision: 5419 >> >> Log: >> Splits reading of block data and decoding of block data. >> Introduces ALSBlockData struct. > You are missing the "why" part, that should be explained in the commit > message Yes, sorry.
> also this needs a benchmark as there are many additional dereferences > added It is a necessary evil to support MCC. If it would be faster the "old" way for non-MCC files, would this reason to have both, a split read & decode function pair and an all-in-one function? I think a benchmark is usefull to judge if we should spend time thinking about alternatives to the many dereferences or not [...] This is a 30% difference which makes me think to try these alternatives.
What comes into my mind would be to use local copies, thus dereferencing the field of *bd just twice. One at the top and one at the bottom of the function.
I tested using local copies instead of dereferencing: [...] That's a 4% gain so I think local copies don't pay off...
Other alternatives?
i would first confirm that gcc did not do something stupid about inlining. Or more precissely not inlining some random unrelated function after the file got bigger ...
How to do that?
nm -S foobar.o will show you things that are not inlined and how large they are you can also use gcc to compile code to .s files and use grep on them [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB I have never wished to cater to the crowd; for what I know they do not approve, and what they approve I do not know. -- Epicurus
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 01:32:15PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 11:29:55AM +0200, Thilo Borgmann wrote:
Thilo Borgmann schrieb:
Michael Niedermayer schrieb:
On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote: > Michael Niedermayer schrieb: >> On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote: >>> Author: thilo.borgmann >>> Date: Tue Oct 20 15:00:40 2009 >>> New Revision: 5419 >>> >>> Log: >>> Splits reading of block data and decoding of block data. >>> Introduces ALSBlockData struct. >> You are missing the "why" part, that should be explained in the commit >> message > Yes, sorry. > >> also this needs a benchmark as there are many additional dereferences >> added > It is a necessary evil to support MCC. If it would be faster the "old" > way for non-MCC files, would this reason to have both, a split read & > decode function pair and an all-in-one function? I think a benchmark is usefull to judge if we should spend time thinking about alternatives to the many dereferences or not [...] This is a 30% difference which makes me think to try these alternatives.
What comes into my mind would be to use local copies, thus dereferencing the field of *bd just twice. One at the top and one at the bottom of the function.
I tested using local copies instead of dereferencing: [...] That's a 4% gain so I think local copies don't pay off...
Other alternatives? i would first confirm that gcc did not do something stupid about inlining. Or more precissely not inlining some random unrelated function after the file got bigger ... How to do that?
nm -S foobar.o will show you things that are not inlined and how large they are
The BSD version does not have the option to show the size instead of the 'value'...
you can also use gcc to compile code to .s files and use grep on them
... so this seems to be necessary. What am I grepping for? -Thilo
On Thu, Oct 22, 2009 at 08:26:12PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 01:32:15PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 11:29:55AM +0200, Thilo Borgmann wrote:
Thilo Borgmann schrieb:
Michael Niedermayer schrieb: > On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote: >> Michael Niedermayer schrieb: >>> On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote: >>>> Author: thilo.borgmann >>>> Date: Tue Oct 20 15:00:40 2009 >>>> New Revision: 5419 >>>> >>>> Log: >>>> Splits reading of block data and decoding of block data. >>>> Introduces ALSBlockData struct. >>> You are missing the "why" part, that should be explained in the commit >>> message >> Yes, sorry. >> >>> also this needs a benchmark as there are many additional dereferences >>> added >> It is a necessary evil to support MCC. If it would be faster the "old" >> way for non-MCC files, would this reason to have both, a split read & >> decode function pair and an all-in-one function? > I think a benchmark is usefull to judge if we should spend time thinking > about alternatives to the many dereferences or not [...] This is a 30% difference which makes me think to try these alternatives.
What comes into my mind would be to use local copies, thus dereferencing the field of *bd just twice. One at the top and one at the bottom of the function.
I tested using local copies instead of dereferencing: [...] That's a 4% gain so I think local copies don't pay off...
Other alternatives? i would first confirm that gcc did not do something stupid about inlining. Or more precissely not inlining some random unrelated function after the file got bigger ... How to do that?
nm -S foobar.o will show you things that are not inlined and how large they are
The BSD version does not have the option to show the size instead of the 'value'...
you can also use gcc to compile code to .s files and use grep on them
... so this seems to be necessary. What am I grepping for?
here egrep '(^[^.]*.:|call[[:space:]]*[a-z])' shows function names and all calls to non inlined functions a diff of this from old and new could be interresting [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Observe your enemies, for they first find out your faults. -- Antisthenes
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 08:26:12PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 01:32:15PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 11:29:55AM +0200, Thilo Borgmann wrote:
Thilo Borgmann schrieb: > Michael Niedermayer schrieb: >> On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote: >>> Michael Niedermayer schrieb: >>>> On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote: >>>>> Author: thilo.borgmann >>>>> Date: Tue Oct 20 15:00:40 2009 >>>>> New Revision: 5419 >>>>> >>>>> Log: >>>>> Splits reading of block data and decoding of block data. >>>>> Introduces ALSBlockData struct. >>>> You are missing the "why" part, that should be explained in the commit >>>> message >>> Yes, sorry. >>> >>>> also this needs a benchmark as there are many additional dereferences >>>> added >>> It is a necessary evil to support MCC. If it would be faster the "old" >>> way for non-MCC files, would this reason to have both, a split read & >>> decode function pair and an all-in-one function? >> I think a benchmark is usefull to judge if we should spend time thinking >> about alternatives to the many dereferences or not [...] > This is a 30% difference which makes me think to try these alternatives. > > What comes into my mind would be to use local copies, thus dereferencing > the field of *bd just twice. One at the top and one at the bottom of the > function. > I tested using local copies instead of dereferencing: [...] That's a 4% gain so I think local copies don't pay off...
Other alternatives? i would first confirm that gcc did not do something stupid about inlining. Or more precissely not inlining some random unrelated function after the file got bigger ... How to do that? nm -S foobar.o will show you things that are not inlined and how large they are The BSD version does not have the option to show the size instead of the 'value'...
you can also use gcc to compile code to .s files and use grep on them ... so this seems to be necessary. What am I grepping for?
here egrep '(^[^.]*.:|call[[:space:]]*[a-z])' shows function names and all calls to non inlined functions a diff of this from old and new could be interresting
Ok, reading this thread again I began not to feel too sure about if we are talking about the diff between "local variables <-> dereferences" or "combined <-> separate" functions. So I grepped both files for both cases. I'm not trained in reading the diff's so I included the grep output for all cases. For the local<->dereferes case, the function I used the local variables in is "read_var_block_data" - I don't know but might be helpful... Zip attached. -Thilo
On Fri, Oct 23, 2009 at 01:03:56PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 08:26:12PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 01:32:15PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 11:29:55AM +0200, Thilo Borgmann wrote: > Thilo Borgmann schrieb: >> Michael Niedermayer schrieb: >>> On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote: >>>> Michael Niedermayer schrieb: >>>>> On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote: >>>>>> Author: thilo.borgmann >>>>>> Date: Tue Oct 20 15:00:40 2009 >>>>>> New Revision: 5419 >>>>>> >>>>>> Log: >>>>>> Splits reading of block data and decoding of block data. >>>>>> Introduces ALSBlockData struct. >>>>> You are missing the "why" part, that should be explained in the commit >>>>> message >>>> Yes, sorry. >>>> >>>>> also this needs a benchmark as there are many additional dereferences >>>>> added >>>> It is a necessary evil to support MCC. If it would be faster the "old" >>>> way for non-MCC files, would this reason to have both, a split read & >>>> decode function pair and an all-in-one function? >>> I think a benchmark is usefull to judge if we should spend time thinking >>> about alternatives to the many dereferences or not [...] >> This is a 30% difference which makes me think to try these alternatives. >> >> What comes into my mind would be to use local copies, thus dereferencing >> the field of *bd just twice. One at the top and one at the bottom of the >> function. >> > I tested using local copies instead of dereferencing: [...] > That's a 4% gain so I think local copies don't pay off... > > Other alternatives? i would first confirm that gcc did not do something stupid about inlining. Or more precissely not inlining some random unrelated function after the file got bigger ... How to do that? nm -S foobar.o will show you things that are not inlined and how large they are The BSD version does not have the option to show the size instead of the 'value'...
you can also use gcc to compile code to .s files and use grep on them ... so this seems to be necessary. What am I grepping for?
here egrep '(^[^.]*.:|call[[:space:]]*[a-z])' shows function names and all calls to non inlined functions a diff of this from old and new could be interresting
Ok, reading this thread again I began not to feel too sure about if we are talking about the diff between "local variables <-> dereferences" or "combined <-> separate" functions.
So I grepped both files for both cases. I'm not trained in reading the diff's so I included the grep output for all cases.
you need a different grep line its suposed to look like (for huffyuv for example) add_left_prediction: sub_left_prediction: decode_422_bitstream: decode_gray_bitstream: decode_bgr_bitstream: draw_slice: encode_end: call av_freep call av_freep call av_freep call av_freep call av_freep alloc_temp: call av_malloc call av_malloc call av_malloc call av_malloc call av_malloc decode_end: call av_freep call av_freep call av_freep call av_freep call free_vlc call free_vlc call free_vlc call free_vlc call free_vlc call free_vlc [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB It is dangerous to be right in matters on which the established authorities are wrong. -- Voltaire
Michael Niedermayer schrieb:
On Fri, Oct 23, 2009 at 01:03:56PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 08:26:12PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb:
On Thu, Oct 22, 2009 at 01:32:15PM +0200, Thilo Borgmann wrote:
Michael Niedermayer schrieb: > On Thu, Oct 22, 2009 at 11:29:55AM +0200, Thilo Borgmann wrote: >> Thilo Borgmann schrieb: >>> Michael Niedermayer schrieb: >>>> On Wed, Oct 21, 2009 at 12:33:21PM +0200, Thilo Borgmann wrote: >>>>> Michael Niedermayer schrieb: >>>>>> On Tue, Oct 20, 2009 at 03:00:40PM +0200, thilo.borgmann wrote: >>>>>>> Author: thilo.borgmann >>>>>>> Date: Tue Oct 20 15:00:40 2009 >>>>>>> New Revision: 5419 >>>>>>> >>>>>>> Log: >>>>>>> Splits reading of block data and decoding of block data. >>>>>>> Introduces ALSBlockData struct. >>>>>> You are missing the "why" part, that should be explained in the commit >>>>>> message >>>>> Yes, sorry. >>>>> >>>>>> also this needs a benchmark as there are many additional dereferences >>>>>> added >>>>> It is a necessary evil to support MCC. If it would be faster the "old" >>>>> way for non-MCC files, would this reason to have both, a split read & >>>>> decode function pair and an all-in-one function? >>>> I think a benchmark is usefull to judge if we should spend time thinking >>>> about alternatives to the many dereferences or not > [...] >>> This is a 30% difference which makes me think to try these alternatives. >>> >>> What comes into my mind would be to use local copies, thus dereferencing >>> the field of *bd just twice. One at the top and one at the bottom of the >>> function. >>> >> I tested using local copies instead of dereferencing: > [...] >> That's a 4% gain so I think local copies don't pay off... >> >> Other alternatives? > i would first confirm that gcc did not do something stupid about inlining. > Or more precissely not inlining some random unrelated function after the > file got bigger ... How to do that? nm -S foobar.o will show you things that are not inlined and how large they are The BSD version does not have the option to show the size instead of the 'value'...
you can also use gcc to compile code to .s files and use grep on them ... so this seems to be necessary. What am I grepping for? here egrep '(^[^.]*.:|call[[:space:]]*[a-z])' shows function names and all calls to non inlined functions a diff of this from old and new could be interresting Ok, reading this thread again I began not to feel too sure about if we are talking about the diff between "local variables <-> dereferences" or "combined <-> separate" functions.
So I grepped both files for both cases. I'm not trained in reading the diff's so I included the grep output for all cases.
you need a different grep line its suposed to look like (for huffyuv for example) [...]
Here they are. -Thilo
participants (3)
-
Michael Niedermayer -
Thilo Borgmann -
thilo.borgmann