Mercurial > libavcodec.hg
comparison mpegvideo.c @ 220:0b234715e205 libavcodec
(commit by michael)
mmx & mmx2 quantizer
c dct permutation bugfix
dont copy input on intra only encodings if it can be avoided
dont draw edges on intra only stuff
author | arpi_esp |
---|---|
date | Sun, 27 Jan 2002 13:30:18 +0000 |
parents | de372d04039c |
children | ec1bc02a0a47 |
comparison
equal
deleted
inserted
replaced
219:5b88ee1abf97 | 220:0b234715e205 |
---|---|
33 static int rate_estimate_qscale(MpegEncContext *s); | 33 static int rate_estimate_qscale(MpegEncContext *s); |
34 static void dct_unquantize_mpeg1_c(MpegEncContext *s, | 34 static void dct_unquantize_mpeg1_c(MpegEncContext *s, |
35 DCTELEM *block, int n, int qscale); | 35 DCTELEM *block, int n, int qscale); |
36 static void dct_unquantize_h263_c(MpegEncContext *s, | 36 static void dct_unquantize_h263_c(MpegEncContext *s, |
37 DCTELEM *block, int n, int qscale); | 37 DCTELEM *block, int n, int qscale); |
38 static int dct_quantize(MpegEncContext *s, DCTELEM *block, int n, int qscale); | |
39 static int dct_quantize_mmx(MpegEncContext *s, | |
40 DCTELEM *block, int n, | |
41 int qscale); | |
42 static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w); | 38 static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w); |
43 | 39 static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); |
40 | |
41 int (*dct_quantize)(MpegEncContext *s, DCTELEM *block, int n, int qscale)= dct_quantize_c; | |
44 void (*draw_edges)(UINT8 *buf, int wrap, int width, int height, int w)= draw_edges_c; | 42 void (*draw_edges)(UINT8 *buf, int wrap, int width, int height, int w)= draw_edges_c; |
45 | 43 |
46 #define EDGE_WIDTH 16 | 44 #define EDGE_WIDTH 16 |
47 | 45 |
48 /* enable all paranoid tests for rounding, overflows, etc... */ | 46 /* enable all paranoid tests for rounding, overflows, etc... */ |
72 /* default motion estimation */ | 70 /* default motion estimation */ |
73 int motion_estimation_method = ME_LOG; | 71 int motion_estimation_method = ME_LOG; |
74 | 72 |
75 extern UINT8 zigzag_end[64]; | 73 extern UINT8 zigzag_end[64]; |
76 | 74 |
77 /* XXX: should use variable shift ? */ | 75 static void convert_matrix(int *qmat, UINT16 *qmat16, const UINT16 *quant_matrix, int qscale) |
78 #define QMAT_SHIFT_MMX 19 | |
79 #define QMAT_SHIFT 25 | |
80 | |
81 static void convert_matrix(int *qmat, const UINT16 *quant_matrix, int qscale) | |
82 { | 76 { |
83 int i; | 77 int i; |
84 | 78 |
85 if (av_fdct == jpeg_fdct_ifast) { | 79 if (av_fdct == jpeg_fdct_ifast) { |
86 for(i=0;i<64;i++) { | 80 for(i=0;i<64;i++) { |
87 /* 16 <= qscale * quant_matrix[i] <= 7905 */ | 81 /* 16 <= qscale * quant_matrix[i] <= 7905 */ |
88 /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */ | 82 /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */ |
83 /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */ | |
84 /* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */ | |
89 | 85 |
90 qmat[i] = (int)((UINT64_C(1) << (QMAT_SHIFT + 11)) / | 86 qmat[block_permute_op(i)] = (int)((UINT64_C(1) << (QMAT_SHIFT + 11)) / |
91 (aanscales[i] * qscale * quant_matrix[i])); | 87 (aanscales[i] * qscale * quant_matrix[block_permute_op(i)])); |
92 } | 88 } |
93 } else { | 89 } else { |
94 for(i=0;i<64;i++) { | 90 for(i=0;i<64;i++) { |
95 /* We can safely suppose that 16 <= quant_matrix[i] <= 255 | 91 /* We can safely suppose that 16 <= quant_matrix[i] <= 255 |
96 So 16 <= qscale * quant_matrix[i] <= 7905 | 92 So 16 <= qscale * quant_matrix[i] <= 7905 |
97 so (1 << QMAT_SHIFT) / 16 >= qmat[i] >= (1 << QMAT_SHIFT) / 7905 | 93 so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905 |
94 so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67 | |
98 */ | 95 */ |
99 qmat[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]); | 96 qmat[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]); |
97 qmat16[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[block_permute_op(i)]); | |
100 } | 98 } |
101 } | 99 } |
102 } | 100 } |
103 | 101 |
104 /* init common structure for both encoder and decoder */ | 102 /* init common structure for both encoder and decoder */ |
416 | 414 |
417 /* generic function for encode/decode called after a frame has been coded/decoded */ | 415 /* generic function for encode/decode called after a frame has been coded/decoded */ |
418 void MPV_frame_end(MpegEncContext *s) | 416 void MPV_frame_end(MpegEncContext *s) |
419 { | 417 { |
420 /* draw edge for correct motion prediction if outside */ | 418 /* draw edge for correct motion prediction if outside */ |
421 if (s->pict_type != B_TYPE) { | 419 if (s->pict_type != B_TYPE && !s->intra_only) { |
422 if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){ | 420 if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){ |
423 draw_edges(s->current_picture[0], s->linesize, s->mb_width*16, s->mb_height*16, EDGE_WIDTH); | 421 draw_edges(s->current_picture[0], s->linesize, s->mb_width*16, s->mb_height*16, EDGE_WIDTH); |
424 draw_edges(s->current_picture[1], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); | 422 draw_edges(s->current_picture[1], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); |
425 draw_edges(s->current_picture[2], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); | 423 draw_edges(s->current_picture[2], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); |
426 }else{ | 424 }else{ |
455 s->pict_type = I_TYPE; | 453 s->pict_type = I_TYPE; |
456 } | 454 } |
457 avctx->key_frame = (s->pict_type == I_TYPE); | 455 avctx->key_frame = (s->pict_type == I_TYPE); |
458 | 456 |
459 MPV_frame_start(s); | 457 MPV_frame_start(s); |
460 | 458 |
461 for(i=0;i<3;i++) { | 459 for(i=0;i<3;i++) { |
462 UINT8 *src = pict->data[i]; | 460 UINT8 *src = pict->data[i]; |
463 UINT8 *dest = s->current_picture[i]; | 461 UINT8 *dest = s->current_picture[i]; |
464 int src_wrap = pict->linesize[i]; | 462 int src_wrap = pict->linesize[i]; |
465 int dest_wrap = s->linesize; | 463 int dest_wrap = s->linesize; |
470 dest_wrap >>= 1; | 468 dest_wrap >>= 1; |
471 w >>= 1; | 469 w >>= 1; |
472 h >>= 1; | 470 h >>= 1; |
473 } | 471 } |
474 | 472 |
475 for(j=0;j<h;j++) { | 473 if(s->intra_only && dest_wrap==src_wrap){ |
476 memcpy(dest, src, w); | 474 s->current_picture[i] = pict->data[i]; |
477 dest += dest_wrap; | 475 }else { |
478 src += src_wrap; | 476 for(j=0;j<h;j++) { |
479 } | 477 memcpy(dest, src, w); |
478 dest += dest_wrap; | |
479 src += src_wrap; | |
480 } | |
481 } | |
480 s->new_picture[i] = s->current_picture[i]; | 482 s->new_picture[i] = s->current_picture[i]; |
481 } | 483 } |
482 | 484 |
483 encode_picture(s, s->picture_number); | 485 encode_picture(s, s->picture_number); |
484 | 486 |
871 if (s->out_format == FMT_MJPEG) { | 873 if (s->out_format == FMT_MJPEG) { |
872 /* for mjpeg, we do include qscale in the matrix */ | 874 /* for mjpeg, we do include qscale in the matrix */ |
873 s->intra_matrix[0] = default_intra_matrix[0]; | 875 s->intra_matrix[0] = default_intra_matrix[0]; |
874 for(i=1;i<64;i++) | 876 for(i=1;i<64;i++) |
875 s->intra_matrix[i] = (default_intra_matrix[i] * s->qscale) >> 3; | 877 s->intra_matrix[i] = (default_intra_matrix[i] * s->qscale) >> 3; |
876 convert_matrix(s->q_intra_matrix, s->intra_matrix, 8); | 878 convert_matrix(s->q_intra_matrix, s->q_intra_matrix16, s->intra_matrix, 8); |
877 } else { | 879 } else { |
878 convert_matrix(s->q_intra_matrix, s->intra_matrix, s->qscale); | 880 convert_matrix(s->q_intra_matrix, s->q_intra_matrix16, s->intra_matrix, s->qscale); |
879 convert_matrix(s->q_non_intra_matrix, s->non_intra_matrix, s->qscale); | 881 convert_matrix(s->q_non_intra_matrix, s->q_non_intra_matrix16, s->non_intra_matrix, s->qscale); |
880 } | 882 } |
881 | 883 |
882 switch(s->out_format) { | 884 switch(s->out_format) { |
883 case FMT_MJPEG: | 885 case FMT_MJPEG: |
884 mjpeg_picture_header(s); | 886 mjpeg_picture_header(s); |
1009 } else { | 1011 } else { |
1010 /* default quantization values */ | 1012 /* default quantization values */ |
1011 s->y_dc_scale = 8; | 1013 s->y_dc_scale = 8; |
1012 s->c_dc_scale = 8; | 1014 s->c_dc_scale = 8; |
1013 } | 1015 } |
1014 | |
1015 for(i=0;i<6;i++) { | 1016 for(i=0;i<6;i++) { |
1016 int last_index; | 1017 s->block_last_index[i] = dct_quantize(s, s->block[i], i, s->qscale); |
1017 if (av_fdct == jpeg_fdct_ifast) | |
1018 last_index = dct_quantize(s, s->block[i], i, s->qscale); | |
1019 else | |
1020 last_index = dct_quantize_mmx(s, s->block[i], i, s->qscale); | |
1021 s->block_last_index[i] = last_index; | |
1022 } | 1018 } |
1023 | 1019 |
1024 /* huffman encode */ | 1020 /* huffman encode */ |
1025 switch(s->out_format) { | 1021 switch(s->out_format) { |
1026 case FMT_MPEG1: | 1022 case FMT_MPEG1: |
1058 | 1054 |
1059 //if (s->gob_number) | 1055 //if (s->gob_number) |
1060 // fprintf(stderr,"\nNumber of GOB: %d", s->gob_number); | 1056 // fprintf(stderr,"\nNumber of GOB: %d", s->gob_number); |
1061 } | 1057 } |
1062 | 1058 |
1063 static int dct_quantize(MpegEncContext *s, | 1059 static int dct_quantize_c(MpegEncContext *s, |
1064 DCTELEM *block, int n, | 1060 DCTELEM *block, int n, |
1065 int qscale) | 1061 int qscale) |
1066 { | 1062 { |
1067 int i, j, level, last_non_zero, q; | 1063 int i, j, level, last_non_zero, q; |
1068 const int *qmat; | 1064 const int *qmat; |
1155 */ | 1151 */ |
1156 if (level > maxLevel) | 1152 if (level > maxLevel) |
1157 level = maxLevel; | 1153 level = maxLevel; |
1158 else if (level < minLevel) | 1154 else if (level < minLevel) |
1159 level = minLevel; | 1155 level = minLevel; |
1160 block[j] = level; | 1156 |
1161 last_non_zero = i; | |
1162 } else { | |
1163 block[j] = 0; | |
1164 } | |
1165 } | |
1166 return last_non_zero; | |
1167 } | |
1168 | |
1169 static int dct_quantize_mmx(MpegEncContext *s, | |
1170 DCTELEM *block, int n, | |
1171 int qscale) | |
1172 { | |
1173 int i, j, level, last_non_zero, q; | |
1174 const int *qmat; | |
1175 int minLevel, maxLevel; | |
1176 | |
1177 if(s->avctx!=NULL && s->avctx->codec->id==CODEC_ID_MPEG4){ | |
1178 /* mpeg4 */ | |
1179 minLevel= -2048; | |
1180 maxLevel= 2047; | |
1181 }else if(s->out_format==FMT_MPEG1){ | |
1182 /* mpeg1 */ | |
1183 minLevel= -255; | |
1184 maxLevel= 255; | |
1185 }else{ | |
1186 /* h263 / msmpeg4 */ | |
1187 minLevel= -128; | |
1188 maxLevel= 127; | |
1189 } | |
1190 | |
1191 av_fdct (block); | |
1192 | |
1193 /* we need this permutation so that we correct the IDCT | |
1194 permutation. will be moved into DCT code */ | |
1195 block_permute(block); | |
1196 | |
1197 if (s->mb_intra) { | |
1198 if (n < 4) | |
1199 q = s->y_dc_scale; | |
1200 else | |
1201 q = s->c_dc_scale; | |
1202 | |
1203 /* note: block[0] is assumed to be positive */ | |
1204 block[0] = (block[0] + (q >> 1)) / q; | |
1205 i = 1; | |
1206 last_non_zero = 0; | |
1207 if (s->out_format == FMT_H263) { | |
1208 qmat = s->q_non_intra_matrix; | |
1209 } else { | |
1210 qmat = s->q_intra_matrix; | |
1211 } | |
1212 } else { | |
1213 i = 0; | |
1214 last_non_zero = -1; | |
1215 qmat = s->q_non_intra_matrix; | |
1216 } | |
1217 | |
1218 for(;i<64;i++) { | |
1219 j = zigzag_direct[i]; | |
1220 level = block[j]; | |
1221 level = level * qmat[j]; | |
1222 /* XXX: slight error for the low range. Test should be equivalent to | |
1223 (level <= -(1 << (QMAT_SHIFT_MMX - 3)) || level >= (1 << | |
1224 (QMAT_SHIFT_MMX - 3))) | |
1225 */ | |
1226 if (((level << (31 - (QMAT_SHIFT_MMX - 3))) >> (31 - (QMAT_SHIFT_MMX - 3))) != | |
1227 level) { | |
1228 level = level / (1 << (QMAT_SHIFT_MMX - 3)); | |
1229 /* XXX: currently, this code is not optimal. the range should be: | |
1230 mpeg1: -255..255 | |
1231 mpeg2: -2048..2047 | |
1232 h263: -128..127 | |
1233 mpeg4: -2048..2047 | |
1234 */ | |
1235 if (level > maxLevel) | |
1236 level = maxLevel; | |
1237 else if (level < minLevel) | |
1238 level = minLevel; | |
1239 block[j] = level; | 1157 block[j] = level; |
1240 last_non_zero = i; | 1158 last_non_zero = i; |
1241 } else { | 1159 } else { |
1242 block[j] = 0; | 1160 block[j] = 0; |
1243 } | 1161 } |