static void schro_encoder_generate_subband_histogram (SchroEncoderFrame *frame, int component, int index, SchroHistogram *hist, int skip) { int i; int j; int16_t *data; int16_t *line; int stride; int width; int height; int position; schro_histogram_init (hist); position = schro_subband_get_position (index); schro_subband_get (frame->iwt_frame, component, position, &frame->params, &data, &stride, &width, &height); if (index > 0) { for(j=0;j<height;j+=skip){ schro_histogram_add_array_s16 (hist, OFFSET(data, j*stride), width); } schro_histogram_scale (hist, skip); } else { for(j=0;j<height;j+=skip){ line = OFFSET(data, j*stride); for(i=1;i<width;i+=skip){ schro_histogram_add(hist, (line[i] - line[i-1])); } } schro_histogram_scale (hist, skip*skip); } }
static double measure_error_subband (SchroEncoderFrame *frame, int component, int index, int quant_index) { int i; int j; int16_t *data; int16_t *line; int stride; int width; int height; int skip = 1; double error = 0; int q; int quant_factor; int quant_offset; int value; int position; position = schro_subband_get_position (index); schro_subband_get (frame->iwt_frame, component, position, &frame->params, &data, &stride, &width, &height); quant_factor = schro_table_quant[quant_index]; if (frame->params.num_refs > 0) { quant_offset = schro_table_offset_3_8[quant_index]; } else { quant_offset = schro_table_offset_1_2[quant_index]; } error = 0; if (index == 0) { for(j=0;j<height;j+=skip){ line = OFFSET(data, j*stride); for(i=1;i<width;i+=skip){ q = schro_quantise(abs(line[i] - line[i-1]), quant_factor, quant_offset); value = schro_dequantise(q, quant_factor, quant_offset); error += pow2(value - abs(line[i] - line[i-1])); } } } else { for(j=0;j<height;j+=skip){ line = OFFSET(data, j*stride); for(i=0;i<width;i+=skip){ q = schro_quantise(line[i], quant_factor, quant_offset); value = schro_dequantise(q, quant_factor, quant_offset); error += pow2(value - line[i]); } } } error *= skip*skip; return error; }
static void schro_encoder_dump_subband_curves (SchroEncoderFrame *frame) { SchroParams *params = &frame->params; int i; int component; int pos; SCHRO_ASSERT(frame->have_histograms); for(component=0;component<3;component++){ for(i=0;i<1 + 3*params->transform_depth; i++) { int vol; int16_t *data; int stride; int width, height; int j; SchroHistogram *hist; pos = schro_subband_get_position (i); schro_subband_get (frame->iwt_frame, component, pos, &frame->params, &data, &stride, &width, &height); vol = width * height; hist = &frame->subband_hists[component][i]; for(j=0;j<60;j++){ double est_entropy; double error; double est_error; double arith_entropy; error = measure_error_subband (frame, component, i, j); est_entropy = schro_histogram_estimate_entropy ( &frame->subband_hists[component][i], j, params->is_noarith); est_error = schro_histogram_apply_table (hist, &frame->encoder->intra_hist_tables[j]); arith_entropy = schro_encoder_estimate_subband_arith (frame, component, i, j); schro_dump (SCHRO_DUMP_SUBBAND_CURVE, "%d %d %d %g %g %g %g\n", component, i, j, est_entropy/vol, arith_entropy/vol, est_error/vol, error/vol); } } } }
void generate_noise (SchroFrame *frame, int n_transforms, double *weights) { int i; int j; int k; int l; int pos; int w, h, x_offset, y_offset, y_skip; int16_t *data; SchroFrameData *comp; for(k=0;k<3;k++){ comp = frame->components + k; for(l=0;l<1+3*n_transforms;l++){ pos = schro_subband_get_position (l); w = comp->width >> (n_transforms - SCHRO_SUBBAND_SHIFT(pos)); h = comp->height >> (n_transforms - SCHRO_SUBBAND_SHIFT(pos)); y_skip = 1<<(n_transforms - SCHRO_SUBBAND_SHIFT(pos)); if (pos&1) { x_offset = w; } else { x_offset = 0; } if (pos&2) { y_offset = y_skip / 2; } else { y_offset = 0; } //printf("%d %d w %d h %d x_offset %d y_offset %d y_skip %d\n", l, pos, w, h, x_offset, y_offset, y_skip); for(j=0;j<h;j++){ data = OFFSET(comp->data, (j*y_skip + y_offset)*comp->stride); data += x_offset; for(i=0;i<w;i++){ data[i] = rint(random_std()*AMPLITUDE*weights[l]); //data[i] = rint(random_std()*AMPLITUDE); } } } } }
void schro_encoder_init_subbands (SchroEncoderFrame *frame) { int i; int pos; SchroParams *params = &frame->params; for(i=0;i<1+3*params->transform_depth;i++) { pos = schro_subband_get_position (i); schro_subband_get_frame_data (frame->luma_subbands + i, frame->iwt_frame, 0, pos, params); schro_subband_get_frame_data (frame->chroma1_subbands + i, frame->iwt_frame, 0, pos, params); schro_subband_get_frame_data (frame->chroma2_subbands + i, frame->iwt_frame, 0, pos, params); } }
static void schro_encoder_generate_subband_histograms (SchroEncoderFrame *frame) { SchroParams *params = &frame->params; int i; int component; int pos; int skip; for(component=0;component<3;component++){ for(i=0;i<1 + 3*params->transform_depth; i++) { pos = schro_subband_get_position (i); skip = 1<<MAX(0,SCHRO_SUBBAND_SHIFT(pos)-1); schro_encoder_generate_subband_histogram (frame, component, i, &frame->subband_hists[component][i], skip); } } frame->have_histograms = TRUE; }
static void schro_lowdelay_init (SchroLowDelay *lowdelay, SchroFrame *frame, SchroParams *params) { int i; int size; lowdelay->params = params; for(i=0;i<1+3*params->transform_depth;i++){ int position = schro_subband_get_position(i); schro_subband_get_frame_data (lowdelay->luma_subbands + i, frame, 0, position, params); schro_subband_get_frame_data (lowdelay->chroma1_subbands + i, frame, 1, position, params); schro_subband_get_frame_data (lowdelay->chroma2_subbands + i, frame, 2, position, params); } size = 1000; lowdelay->saved_dc_values = schro_malloc (sizeof(int16_t) * size); }
static void schro_encoder_calc_estimates (SchroEncoderFrame *frame) { SchroParams *params = &frame->params; int i; int j; int component; SCHRO_ASSERT(frame->have_histograms); #ifdef DUMP_SUBBAND_CURVES schro_encoder_dump_subband_curves (frame); #endif for(component=0;component<3;component++){ for(i=0;i<1 + 3*params->transform_depth; i++) { for(j=0;j<60;j++){ int vol; int16_t *data; int stride; int width, height; int position; SchroHistogram *hist; position = schro_subband_get_position (i); schro_subband_get (frame->iwt_frame, component, position, &frame->params, &data, &stride, &width, &height); vol = width * height; hist = &frame->subband_hists[component][i]; frame->est_entropy[component][i][j] = schro_histogram_estimate_entropy (hist, j, params->is_noarith); frame->est_error[component][i][j] = schro_histogram_apply_table (hist, &frame->encoder->intra_hist_tables[j]); } } } frame->have_estimate_tables = TRUE; }
void schro_encoder_rate_distortion_test (SchroEncoderFrame *frame) { SchroParams *params = &frame->params; int i; int component; int j; double lambda_mult; double n; double base_lambda; int qsum; base_lambda = 0.1; schro_encoder_generate_subband_histograms (frame); schro_encoder_calc_estimates (frame); for(j=0;j<40;j++){ lambda_mult = pow(1.1, j-20); n = 0; qsum = 0; for(component=0;component<3;component++){ for(i=0;i<1 + 3*params->transform_depth; i++) { int vol; int16_t *data; int stride; int width, height; double lambda; int position; double weight; int quant_index; position = schro_subband_get_position (i); schro_subband_get (frame->iwt_frame, component, position, &frame->params, &data, &stride, &width, &height); vol = width * height; lambda = base_lambda; lambda *= lambda_mult; if (i == 0) { //lambda *= 10; } #if 0 if (component > 0) { lambda *= 0.3; } #endif if (frame->is_ref) { lambda *= 10; } weight = frame->encoder->subband_weights[frame->params.wavelet_filter_index] [frame->params.transform_depth-1][i]; lambda /= weight*weight; quant_index = schro_subband_pick_quant (frame, component, i, lambda); n += frame->est_entropy[component][i][quant_index]; qsum += quant_index; } } schro_dump (SCHRO_DUMP_LAMBDA_CURVE, "%d %g %g %d", j, lambda_mult * base_lambda, n, qsum); } }
static double schro_encoder_estimate_subband_arith (SchroEncoderFrame *frame, int component, int index, int quant_index) { int i; int j; int16_t *data; int16_t *line; int stride; int width; int height; int q; int quant_factor; int quant_offset; int estimated_entropy; SchroArith *arith; int position; arith = schro_arith_new (); schro_arith_estimate_init (arith); position = schro_subband_get_position (index); schro_subband_get (frame->iwt_frame, component, position, &frame->params, &data, &stride, &width, &height); quant_factor = schro_table_quant[quant_index]; quant_offset = schro_table_offset_1_2[quant_index]; if (index == 0) { for(j=0;j<height;j++) { line = OFFSET(data, j*stride); schro_arith_estimate_sint (arith, SCHRO_CTX_ZPZN_F1, SCHRO_CTX_COEFF_DATA, SCHRO_CTX_SIGN_ZERO, 0); for(i=1;i<width;i++) { q = schro_quantise(line[i] - line[i-1], quant_factor, quant_offset); schro_arith_estimate_sint (arith, SCHRO_CTX_ZPZN_F1, SCHRO_CTX_COEFF_DATA, SCHRO_CTX_SIGN_ZERO, q); } } } else { for(j=0;j<height;j++) { line = OFFSET(data, j*stride); for(i=0;i<width;i++) { q = schro_quantise(line[i], quant_factor, quant_offset); schro_arith_estimate_sint (arith, SCHRO_CTX_ZPZN_F1, SCHRO_CTX_COEFF_DATA, SCHRO_CTX_SIGN_ZERO, q); } } } estimated_entropy = 0; estimated_entropy += arith->contexts[SCHRO_CTX_ZPZN_F1].n_bits; estimated_entropy += arith->contexts[SCHRO_CTX_ZP_F2].n_bits; estimated_entropy += arith->contexts[SCHRO_CTX_ZP_F3].n_bits; estimated_entropy += arith->contexts[SCHRO_CTX_ZP_F4].n_bits; estimated_entropy += arith->contexts[SCHRO_CTX_ZP_F5].n_bits; estimated_entropy += arith->contexts[SCHRO_CTX_ZP_F6p].n_bits; estimated_entropy += arith->contexts[SCHRO_CTX_COEFF_DATA].n_bits; estimated_entropy += arith->contexts[SCHRO_CTX_SIGN_ZERO].n_bits; schro_arith_free (arith); return estimated_entropy; }
void schro_encoder_calculate_subband_weights (SchroEncoder *encoder, double (*perceptual_weight)(double)) { int wavelet; int n_levels; double *matrix; int n; int i,j; double column[SCHRO_LIMIT_SUBBANDS]; double *weight; matrix = schro_malloc (sizeof(double)*SCHRO_LIMIT_SUBBANDS*SCHRO_LIMIT_SUBBANDS); weight = schro_malloc (sizeof(double)*CURVE_SIZE*CURVE_SIZE); for(j=0;j<CURVE_SIZE;j++){ for(i=0;i<CURVE_SIZE;i++){ double fv = j*encoder->cycles_per_degree_vert*(1.0/CURVE_SIZE); double fh = i*encoder->cycles_per_degree_horiz*(1.0/CURVE_SIZE); weight[j*CURVE_SIZE+i] = perceptual_weight (sqrt(fv*fv+fh*fh)); } } for(wavelet=0;wavelet<SCHRO_N_WAVELETS;wavelet++) { for(n_levels=1;n_levels<=4;n_levels++){ const float *h_curve[SCHRO_LIMIT_SUBBANDS]; const float *v_curve[SCHRO_LIMIT_SUBBANDS]; int hi[SCHRO_LIMIT_SUBBANDS]; int vi[SCHRO_LIMIT_SUBBANDS]; n = 3*n_levels+1; for(i=0;i<n;i++){ int position = schro_subband_get_position(i); int n_transforms; n_transforms = n_levels - SCHRO_SUBBAND_SHIFT(position); if (position&1) { hi[i] = (n_transforms-1)*2; } else { hi[i] = (n_transforms-1)*2+1; } if (position&2) { vi[i] = (n_transforms-1)*2; } else { vi[i] = (n_transforms-1)*2+1; } h_curve[i] = schro_tables_wavelet_noise_curve[wavelet][hi[i]]; v_curve[i] = schro_tables_wavelet_noise_curve[wavelet][vi[i]]; } if (0) { for(i=0;i<n;i++){ column[i] = weighted_sum(h_curve[i], v_curve[i], weight); matrix[i*n+i] = dot_product (h_curve[i], v_curve[i], h_curve[i], v_curve[i], weight); for(j=i+1;j<n;j++) { matrix[i*n+j] = dot_product (h_curve[i], v_curve[i], h_curve[j], v_curve[j], weight); matrix[j*n+i] = matrix[i*n+j]; } } solve (matrix, column, n); for(i=0;i<n;i++){ if (column[i] < 0) { SCHRO_ERROR("BROKEN wavelet %d n_levels %d", wavelet, n_levels); break; } } SCHRO_DEBUG("wavelet %d n_levels %d", wavelet, n_levels); for(i=0;i<n;i++){ SCHRO_DEBUG("%g", 1.0/sqrt(column[i])); encoder->subband_weights[wavelet][n_levels-1][i] = sqrt(column[i]); } } else { for(i=0;i<n;i++){ int position = schro_subband_get_position(i); int n_transforms; double size; n_transforms = n_levels - SCHRO_SUBBAND_SHIFT(position); size = (1.0/CURVE_SIZE)*(1<<n_transforms); encoder->subband_weights[wavelet][n_levels-1][i] = 1.0/(size * sqrt(weighted_sum(h_curve[i], v_curve[i], weight))); } } } } #if 0 for(wavelet=0;wavelet<8;wavelet++) { for(n_levels=1;n_levels<=4;n_levels++){ double alpha, beta, shift; double gain; alpha = schro_tables_wavelet_gain[wavelet][0]; beta = schro_tables_wavelet_gain[wavelet][1]; shift = (1<<filtershift[wavelet]); n = 3*n_levels+1; gain = shift; for(i=n_levels-1;i>=0;i--){ encoder->subband_weights[wavelet][n_levels-1][1+3*i+0] = sqrt(alpha*beta)*gain; encoder->subband_weights[wavelet][n_levels-1][1+3*i+1] = sqrt(alpha*beta)*gain; encoder->subband_weights[wavelet][n_levels-1][1+3*i+2] = sqrt(beta*beta)*gain; gain *= alpha; gain *= shift; } encoder->subband_weights[wavelet][n_levels-1][0] = gain / shift; if (wavelet == 3 && n_levels == 3) { for(i=0;i<10;i++){ SCHRO_ERROR("%g", encoder->subband_weights[wavelet][n_levels-1][i]); } } } } #endif schro_free(weight); schro_free(matrix); }