Mercurial > libavcodec.hg
comparison mpegvideo.c @ 945:463f7260b155 libavcodec
trellis quantization
author | michaelni |
---|---|
date | Tue, 31 Dec 2002 17:23:56 +0000 |
parents | caa77cd960c0 |
children | 4f522c9e6099 |
comparison
equal
deleted
inserted
replaced
944:927c246f1f6d | 945:463f7260b155 |
---|---|
39 DCTELEM *block, int n, int qscale); | 39 DCTELEM *block, int n, int qscale); |
40 static void dct_unquantize_h263_c(MpegEncContext *s, | 40 static void dct_unquantize_h263_c(MpegEncContext *s, |
41 DCTELEM *block, int n, int qscale); | 41 DCTELEM *block, int n, int qscale); |
42 static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w); | 42 static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w); |
43 static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); | 43 static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); |
44 static int dct_quantize_trellis_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); | |
44 | 45 |
45 void (*draw_edges)(UINT8 *buf, int wrap, int width, int height, int w)= draw_edges_c; | 46 void (*draw_edges)(UINT8 *buf, int wrap, int width, int height, int w)= draw_edges_c; |
46 | 47 |
47 | 48 |
48 /* enable all paranoid tests for rounding, overflows, etc... */ | 49 /* enable all paranoid tests for rounding, overflows, etc... */ |
120 /* We can safely suppose that 16 <= quant_matrix[i] <= 255 | 121 /* We can safely suppose that 16 <= quant_matrix[i] <= 255 |
121 So 16 <= qscale * quant_matrix[i] <= 7905 | 122 So 16 <= qscale * quant_matrix[i] <= 7905 |
122 so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905 | 123 so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905 |
123 so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67 | 124 so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67 |
124 */ | 125 */ |
125 qmat [qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]); | 126 qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / (qscale * quant_matrix[j])); |
127 // qmat [qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]); | |
126 qmat16[qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[j]); | 128 qmat16[qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[j]); |
127 | 129 |
128 if(qmat16[qscale][i]==0 || qmat16[qscale][i]==128*256) qmat16[qscale][i]=128*256-1; | 130 if(qmat16[qscale][i]==0 || qmat16[qscale][i]==128*256) qmat16[qscale][i]=128*256-1; |
129 qmat16_bias[qscale][i]= ROUNDED_DIV(bias<<(16-QUANT_BIAS_SHIFT), qmat16[qscale][i]); | 131 qmat16_bias[qscale][i]= ROUNDED_DIV(bias<<(16-QUANT_BIAS_SHIFT), qmat16[qscale][i]); |
130 } | 132 } |
225 MPV_common_init_armv4l(s); | 227 MPV_common_init_armv4l(s); |
226 #endif | 228 #endif |
227 #ifdef ARCH_POWERPC | 229 #ifdef ARCH_POWERPC |
228 MPV_common_init_ppc(s); | 230 MPV_common_init_ppc(s); |
229 #endif | 231 #endif |
232 | |
233 if(s->flags&CODEC_FLAG_TRELLIS_QUANT){ | |
234 s->dct_quantize= dct_quantize_trellis_c; //move before MPV_common_init_* | |
235 } | |
230 | 236 |
231 switch(s->idct_permutation_type){ | 237 switch(s->idct_permutation_type){ |
232 case FF_NO_IDCT_PERM: | 238 case FF_NO_IDCT_PERM: |
233 for(i=0; i<64; i++) | 239 for(i=0; i<64; i++) |
234 s->idct_permutation[i]= i; | 240 s->idct_permutation[i]= i; |
3251 s->ptr_lastgob = pbBufPtr(&s->pb); | 3257 s->ptr_lastgob = pbBufPtr(&s->pb); |
3252 //fprintf(stderr,"\nGOB: %2d size: %d (last)", s->gob_number, pdif); | 3258 //fprintf(stderr,"\nGOB: %2d size: %d (last)", s->gob_number, pdif); |
3253 } | 3259 } |
3254 } | 3260 } |
3255 | 3261 |
3262 static int dct_quantize_trellis_c(MpegEncContext *s, | |
3263 DCTELEM *block, int n, | |
3264 int qscale, int *overflow){ | |
3265 const int *qmat; | |
3266 const UINT8 *scantable= s->intra_scantable.scantable; | |
3267 int max=0; | |
3268 unsigned int threshold1, threshold2; | |
3269 int bias=0; | |
3270 int run_tab[65]; | |
3271 int last_run[65]; | |
3272 int level_tab[65]; | |
3273 int last_level[65]; | |
3274 int score_tab[65]; | |
3275 int last_score[65]; | |
3276 int coeff[4][64]; | |
3277 int coeff_count[64]; | |
3278 int lambda, qmul, qadd, start_i, best_i, best_score, last_non_zero, i; | |
3279 const int esc_length= s->ac_esc_length; | |
3280 uint8_t * length; | |
3281 uint8_t * last_length; | |
3282 | |
3283 s->fdct (block); | |
3284 | |
3285 qmul= qscale*16; | |
3286 qadd= ((qscale-1)|1)*8; | |
3287 | |
3288 if (s->mb_intra) { | |
3289 int q; | |
3290 if (!s->h263_aic) { | |
3291 if (n < 4) | |
3292 q = s->y_dc_scale; | |
3293 else | |
3294 q = s->c_dc_scale; | |
3295 q = q << 3; | |
3296 } else{ | |
3297 /* For AIC we skip quant/dequant of INTRADC */ | |
3298 q = 1 << 3; | |
3299 qadd=0; | |
3300 } | |
3301 | |
3302 /* note: block[0] is assumed to be positive */ | |
3303 block[0] = (block[0] + (q >> 1)) / q; | |
3304 start_i = 1; | |
3305 last_non_zero = 0; | |
3306 qmat = s->q_intra_matrix[qscale]; | |
3307 if(s->mpeg_quant) | |
3308 bias= 1<<(QMAT_SHIFT-1); | |
3309 length = s->intra_ac_vlc_length; | |
3310 last_length= s->intra_ac_vlc_last_length; | |
3311 } else { | |
3312 start_i = 0; | |
3313 last_non_zero = -1; | |
3314 qmat = s->q_inter_matrix[qscale]; | |
3315 length = s->inter_ac_vlc_length; | |
3316 last_length= s->inter_ac_vlc_last_length; | |
3317 } | |
3318 | |
3319 threshold1= (1<<QMAT_SHIFT) - bias - 1; | |
3320 threshold2= (threshold1<<1); | |
3321 //printf("%d %d %d\n", qmat[1], QMAT_SHIFT, qscale); | |
3322 for(i=start_i; i<64; i++) { | |
3323 const int j = scantable[i]; | |
3324 const int k= i-start_i; | |
3325 int level = block[j]; | |
3326 level = level * qmat[j]; | |
3327 | |
3328 // if( bias+level >= (1<<(QMAT_SHIFT - 3)) | |
3329 // || bias-level >= (1<<(QMAT_SHIFT - 3))){ | |
3330 if(((unsigned)(level+threshold1))>threshold2){ | |
3331 if(level>0){ | |
3332 level= (bias + level)>>QMAT_SHIFT; | |
3333 coeff[0][k]= level; | |
3334 coeff[1][k]= level-1; | |
3335 coeff[2][k]= level-2; | |
3336 coeff[3][k]= level-3; | |
3337 coeff_count[k]= FFMIN(level, 4); | |
3338 }else{ | |
3339 level= (bias - level)>>QMAT_SHIFT; | |
3340 coeff[0][k]= -level; | |
3341 coeff[1][k]= -level+1; | |
3342 coeff[2][k]= -level+2; | |
3343 coeff[3][k]= -level+3; | |
3344 coeff_count[k]= FFMIN(level, 4); | |
3345 } | |
3346 max |=level; | |
3347 last_non_zero = i; | |
3348 }else{ | |
3349 if(level < 0) | |
3350 coeff[0][k]= -1; | |
3351 else | |
3352 coeff[0][k]= 1; | |
3353 coeff_count[k]= 1; | |
3354 } | |
3355 } | |
3356 | |
3357 *overflow= s->max_qcoeff < max; //overflow might have happend | |
3358 | |
3359 if(last_non_zero < start_i){ | |
3360 memset(block + start_i, 0, (64-start_i)*sizeof(DCTELEM)); | |
3361 return last_non_zero; | |
3362 } | |
3363 | |
3364 lambda= (qscale*qscale*64*82 + 50)/100; //FIXME finetune | |
3365 | |
3366 score_tab[0]= | |
3367 last_score[0]= 0; | |
3368 //printf("qscale:%d\n", qscale); | |
3369 for(i=0; i<=last_non_zero - start_i; i++){ | |
3370 int level_index, run, j; | |
3371 const int dct_coeff= block[ scantable[i + start_i] ]; | |
3372 const int zero_distoration= dct_coeff*dct_coeff; | |
3373 int best_score=256*256*256*120, best_last_score= 256*256*256*120; | |
3374 | |
3375 //printf("%2d %5d ", i, dct_coeff); | |
3376 | |
3377 for(level_index=0; level_index < coeff_count[i]; level_index++){ | |
3378 int distoration; | |
3379 int level= coeff[level_index][i]; | |
3380 int unquant_coeff; | |
3381 | |
3382 assert(level); | |
3383 | |
3384 if(s->out_format == FMT_H263){ | |
3385 if(level>0){ | |
3386 unquant_coeff= level*qmul + qadd; | |
3387 }else{ | |
3388 unquant_coeff= level*qmul - qadd; | |
3389 } | |
3390 } //FIXME else | |
3391 //printf("(%d %d) ", level, unquant_coeff); | |
3392 distoration= (unquant_coeff - dct_coeff) * (unquant_coeff - dct_coeff); | |
3393 | |
3394 level+=64; | |
3395 if((level&(~127)) == 0){ | |
3396 for(run=0; run<=i; run++){ | |
3397 int score= distoration + length[UNI_ENC_INDEX(run, level)]*lambda; | |
3398 score += score_tab[i-run]; | |
3399 | |
3400 if(score < best_score){ | |
3401 best_score= | |
3402 score_tab[i+1]= score; | |
3403 run_tab[i+1]= run; | |
3404 level_tab[i+1]= level-64; | |
3405 } | |
3406 } | |
3407 | |
3408 if(s->out_format == FMT_H263){ | |
3409 for(run=0; run<=i; run++){ | |
3410 int score= distoration + last_length[UNI_ENC_INDEX(run, level)]*lambda; | |
3411 score += score_tab[i-run]; | |
3412 if(score < best_last_score){ | |
3413 best_last_score= | |
3414 last_score[i+1]= score; | |
3415 last_run[i+1]= run; | |
3416 last_level[i+1]= level-64; | |
3417 } | |
3418 } | |
3419 } | |
3420 }else{ | |
3421 distoration += esc_length*lambda; | |
3422 for(run=0; run<=i; run++){ | |
3423 int score= distoration + score_tab[i-run]; | |
3424 | |
3425 if(score < best_score){ | |
3426 best_score= | |
3427 score_tab[i+1]= score; | |
3428 run_tab[i+1]= run; | |
3429 level_tab[i+1]= level-64; | |
3430 } | |
3431 } | |
3432 | |
3433 if(s->out_format == FMT_H263){ | |
3434 for(run=0; run<=i; run++){ | |
3435 int score= distoration + score_tab[i-run]; | |
3436 if(score < best_last_score){ | |
3437 best_last_score= | |
3438 last_score[i+1]= score; | |
3439 last_run[i+1]= run; | |
3440 last_level[i+1]= level-64; | |
3441 } | |
3442 } | |
3443 } | |
3444 } | |
3445 } | |
3446 | |
3447 for(j=0; j<=i; j++){ | |
3448 score_tab[j] += zero_distoration; | |
3449 // printf("%6d ", score_tab[j]); | |
3450 } | |
3451 // printf("%6d ", score_tab[j]); | |
3452 | |
3453 // printf("last: "); | |
3454 if(s->out_format == FMT_H263){ | |
3455 for(j=0; j<=i; j++){ | |
3456 last_score[j] += zero_distoration; | |
3457 // printf("%6d ", last_score[j]); | |
3458 } | |
3459 // printf("%6d ", last_score[j]); | |
3460 } | |
3461 // printf("\n"); | |
3462 } | |
3463 | |
3464 if(s->out_format != FMT_H263){ | |
3465 for(i=0; i<=last_non_zero - start_i + 1; i++){ | |
3466 last_score[i]= score_tab[i]; | |
3467 if(i) last_score[i] += lambda*2; //FIXME exacter? | |
3468 last_run[i]= run_tab[i]; | |
3469 last_level[i]= level_tab[i]; | |
3470 } | |
3471 } | |
3472 | |
3473 //FIXME add some cbp penalty | |
3474 best_i= 0; | |
3475 best_score= 256*256*256*120; | |
3476 for(i=0; i<=last_non_zero - start_i + 1; i++){ | |
3477 int score= last_score[i]; | |
3478 if(score < best_score){ | |
3479 best_score= score; | |
3480 best_i= i; | |
3481 } | |
3482 } | |
3483 | |
3484 last_non_zero= best_i - 1 + start_i; | |
3485 memset(block + start_i, 0, (64-start_i)*sizeof(DCTELEM)); | |
3486 | |
3487 if(last_non_zero < start_i) | |
3488 return last_non_zero; | |
3489 | |
3490 i= best_i; | |
3491 //printf("%d %d %d %d %d\n", last_level[i], i, start_i, last_non_zero, best_score); | |
3492 assert(last_level[i]); | |
3493 //FIXME use permutated scantable | |
3494 block[ s->idct_permutation[ scantable[last_non_zero] ] ]= last_level[i]; | |
3495 i -= last_run[i] + 1; | |
3496 | |
3497 for(;i>0 ; i -= run_tab[i] + 1){ | |
3498 const int j= s->idct_permutation[ scantable[i - 1 + start_i] ]; | |
3499 | |
3500 block[j]= level_tab[i]; | |
3501 assert(block[j]); | |
3502 } | |
3503 | |
3504 return last_non_zero; | |
3505 } | |
3506 | |
3256 static int dct_quantize_c(MpegEncContext *s, | 3507 static int dct_quantize_c(MpegEncContext *s, |
3257 DCTELEM *block, int n, | 3508 DCTELEM *block, int n, |
3258 int qscale, int *overflow) | 3509 int qscale, int *overflow) |
3259 { | 3510 { |
3260 int i, j, level, last_non_zero, q; | 3511 int i, j, level, last_non_zero, q; |