📄 xvid_bench.c
字号:
nb = 0; pos = 0; t = -gettime_usec(); while(1) { int y; memset(&xframe, 0, sizeof(xframe)); xframe.version = XVID_VERSION; xframe.bitstream = buf + pos; xframe.length = buf_size - pos; xframe.output.plane[0] = (uint8_t*)(((size_t)yuv_out + 15) & ~15); xframe.output.plane[1] = (uint8_t*)xframe.output.plane[0] + bps*height; xframe.output.plane[2] = (uint8_t*)xframe.output.plane[1] + bps/2; xframe.output.stride[0] = bps; xframe.output.stride[1] = bps; xframe.output.stride[2] = bps; xframe.output.csp = XVID_CSP_I420; xerr = xvid_decore(dechandle, XVID_DEC_DECODE, &xframe, 0); if (xerr<0) { printf("ERROR: decoding failed for frame #%d (err=%d)!\n", nb, xerr); break; } else if (xerr==0) break; else if (verbose>0) printf("#%d %d\n", nb, xerr ); pos += xerr; nb++; for(y=0; y<height/2; ++y) { chksum = calc_crc((uint8_t*)xframe.output.plane[0] + (2*y+0)*bps, width, chksum); chksum = calc_crc((uint8_t*)xframe.output.plane[0] + (2*y+1)*bps, width, chksum); chksum = calc_crc((uint8_t*)xframe.output.plane[1] + y*bps, width/2, chksum); chksum = calc_crc((uint8_t*)xframe.output.plane[2] + y*bps, width/2, chksum); } if (pos==buf_size) break; } t += gettime_usec(); if (ref_chksum==0) { if (t>0.) printf( "%d frames decoded in %.3f s -> %.1f FPS Checksum:0x%.8x\n", nb, t*1.e-6f, (float)(nb*1.e6f/t), chksum ); } else { printf("FPS:%.1f Checksum: 0x%.8x Expected:0x%.8x | %s\n", t>0. ? (float)(nb*1.e6f/t) : 0.f, chksum, ref_chksum, (chksum==ref_chksum) ? "OK" : "ERROR"); } End: if (yuv_out!=0) free(yuv_out); if (buf!=0) free(buf); if (dechandle!=0) { xerr= xvid_decore(dechandle, XVID_DEC_DESTROY, NULL, NULL); if (xerr==XVID_ERR_FAIL) printf("ERROR: destroy-decoder failed (err=%d)!\n", xerr); } if (f!=0) fclose(f);}/********************************************************************* * non-regression tests *********************************************************************/void test_bugs1(){ CPU *cpu; uint16_t mpeg_quant_matrices[64*8]; printf( "\n ===== (de)quant4_intra saturation bug? =====\n" ); for(cpu = cpu_list; cpu->name!=0; ++cpu) { int i; int16_t Src[8*8], Dst[8*8]; if (!init_cpu(cpu)) continue; for(i=0; i<64; ++i) Src[i] = i-32; set_intra_matrix( mpeg_quant_matrices, get_default_intra_matrix() ); dequant_mpeg_intra(Dst, Src, 31, 5, mpeg_quant_matrices); printf( "dequant_mpeg_intra with CPU=%s: ", cpu->name); printf( " Out[]= " ); for(i=0; i<64; ++i) printf( "[%d]", Dst[i]); printf( "\n" ); } printf( "\n ===== (de)quant4_inter saturation bug? =====\n" ); for(cpu = cpu_list; cpu->name!=0; ++cpu) { int i; int16_t Src[8*8], Dst[8*8]; if (!init_cpu(cpu)) continue; for(i=0; i<64; ++i) Src[i] = i-32; set_inter_matrix( mpeg_quant_matrices, get_default_inter_matrix() ); dequant_mpeg_inter(Dst, Src, 31, mpeg_quant_matrices); printf( "dequant_mpeg_inter with CPU=%s: ", cpu->name); printf( " Out[]= " ); for(i=0; i<64; ++i) printf( "[%d]", Dst[i]); printf( "\n" ); }}void test_dct_precision_diffs(){ CPU *cpu; DECLARE_ALIGNED_MATRIX(Blk, 8, 8, int16_t, 16); DECLARE_ALIGNED_MATRIX(Blk0, 8, 8, int16_t, 16); printf( "\n ===== fdct/idct precision diffs =====\n" ); for(cpu = cpu_list; cpu->name!=0; ++cpu) { int i; if (!init_cpu(cpu)) continue; for(i=0; i<8*8; ++i) { Blk0[i] = (i*7-i*i) & 0x7f; Blk[i] = Blk0[i]; } fdct(Blk); idct(Blk); printf( " fdct+idct diffs with CPU=%s: \n", cpu->name ); for(i=0; i<8; ++i) { int j; for(j=0; j<8; ++j) printf( " %d ", Blk[i*8+j]-Blk0[i*8+j]); printf("\n"); } printf("\n"); }}void test_quant_bug(){ const int max_Q = 31; int i, n, qm, q; CPU *cpu; DECLARE_ALIGNED_MATRIX(Src, 8, 8, int16_t, 16); DECLARE_ALIGNED_MATRIX(Dst, 8, 8, int16_t, 16); uint8_t Quant[8*8]; CPU cpu_bug_list[] = { { "PLAINC", 0 }, { "MMX ", XVID_CPU_MMX }, {0,0} }; uint16_t Crcs_Inter[2][32]; uint16_t Crcs_Intra[2][32]; DECLARE_ALIGNED_MATRIX(mpeg_quant_matrices, 8, 64, uint16_t, 16); printf( "\n ===== test MPEG4-quantize bug =====\n" ); for(i=0; i<64; ++i) Src[i] = 2048*(i-32)/32;#if 1 for(qm=1; qm<=255; ++qm) { for(i=0; i<8*8; ++i) Quant[i] = qm; set_inter_matrix( mpeg_quant_matrices, Quant ); for(n=0, cpu = cpu_bug_list; cpu->name!=0; ++cpu, ++n) { uint16_t s; if (!init_cpu(cpu)) continue; for(q=1; q<=max_Q; ++q) { emms(); quant_mpeg_inter( Dst, Src, q, mpeg_quant_matrices ); emms(); for(s=0, i=0; i<64; ++i) s+=((uint16_t)Dst[i])^i; Crcs_Inter[n][q] = s; } } for(q=1; q<=max_Q; ++q) for(i=0; i<n-1; ++i) if (Crcs_Inter[i][q]!=Crcs_Inter[i+1][q]) printf( "Discrepancy Inter: qm=%d, q=%d -> %d/%d !\n", qm, q, Crcs_Inter[i][q], Crcs_Inter[i+1][q]); }#endif#if 1 for(qm=1; qm<=255; ++qm) { for(i=0; i<8*8; ++i) Quant[i] = qm; set_intra_matrix( mpeg_quant_matrices, Quant ); for(n=0, cpu = cpu_bug_list; cpu->name!=0; ++cpu, ++n) { uint16_t s; if (!init_cpu(cpu)) continue; for(q=1; q<=max_Q; ++q) { emms(); quant_mpeg_intra( Dst, Src, q, q, mpeg_quant_matrices); emms(); for(s=0, i=0; i<64; ++i) s+=((uint16_t)Dst[i])^i; Crcs_Intra[n][q] = s; } } for(q=1; q<=max_Q; ++q) for(i=0; i<n-1; ++i) if (Crcs_Intra[i][q]!=Crcs_Intra[i+1][q]) printf( "Discrepancy Intra: qm=%d, q=%d -> %d/%d!\n", qm, q, Crcs_Inter[i][q], Crcs_Inter[i+1][q]); }#endif}/*********************************************************************/static uint32_t __inline log2bin_v1(uint32_t value){ int n = 0; while (value) { value >>= 1; n++; } return n;}static const uint8_t log2_tab_16[16] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };static uint32_t __inline log2bin_v2(uint32_t value){ int n = 0; if (value & 0xffff0000) { value >>= 16; n += 16; } if (value & 0xff00) { value >>= 8; n += 8; } if (value & 0xf0) { value >>= 4; n += 4; } return n + log2_tab_16[value];}void test_log2bin(){ const int nb_tests = 3000*speed_ref; int n, crc1=0, crc2=0; uint32_t s, s0; double t1, t2; t1 = gettime_usec(); s0 = (int)(t1*31.241); for(s=s0, n=0; n<nb_tests; ++n, s=(s*12363+31)&0x7fffffff) crc1 += log2bin_v1(s); t1 = (gettime_usec()-t1) / nb_tests; t2 = gettime_usec(); for(s=s0, n=0; n<nb_tests; ++n, s=(s*12363+31)&0x7fffffff) crc2 += log2bin_v2(s); t2 = (gettime_usec() - t2) / nb_tests; printf( "log2bin_v1: %.3f sec crc=%d\n", t1, crc1 ); printf( "log2bin_v2: %.3f sec crc=%d\n", t2, crc2 ); if (crc1!=crc2) printf( " CRC ERROR !\n" );}/*********************************************************************/static void __inline old_gcd(int *num, int *den){ int i = *num; while (i > 1) { if (*num % i == 0 && *den % i == 0) { *num /= i; *den /= i; i = *num; continue; } i--; }}static uint32_t gcd(int num, int den){ int tmp; while( (tmp=num%den) ) { num = den; den = tmp; } return den;}static void __inline new_gcd(int *num, int *den){ const int div = gcd(*num, *den); if (num) { *num /= div; *den /= div; }}void test_gcd(){ const int nb_tests = 10*speed_ref; int i; uint32_t crc1=0, crc2=0; uint32_t n0, n, d0, d; double t1, t2; t1 = gettime_usec(); n0 = 0xfffff & (int)(t1*31.241); d0 = 0xfffff & (int)( ((n0*4123)%17) | 1 ); for(n=n0, d=d0, i=0; i<nb_tests; ++i) { old_gcd(&n, &d); crc1 = (((crc1>>4)^d) + ((crc1<<2)^n) ) & 0xffffff; n = d; d = (d*12363+31) & 0xffff; d |= !d; } t1 = (gettime_usec()-t1) / nb_tests; t2 = gettime_usec(); for(n=n0, d=d0, i=0; i<nb_tests; ++i) { new_gcd(&n, &d); crc2 = (((crc2>>4)^d) + ((crc2<<2)^n) ) & 0xffffff; n = d; d = (d*12363+31) & 0xffff; d |= !d; } t2 = (gettime_usec() - t2) / nb_tests; printf( "old_gcd: %.3f sec crc=%d\n", t1, crc1 ); printf( "new_gcd: %.3f sec crc=%d\n", t2, crc2 ); if (crc1!=crc2) printf( " CRC ERROR !\n" );}/********************************************************************* * test compiler *********************************************************************/void test_compiler() { int nb_err = 0; int32_t v; if (sizeof(uint16_t)<2) { printf( "ERROR: sizeof(uint16_t)<2 !!\n" ); nb_err++; } if (sizeof(int16_t)<2) { printf( "ERROR: sizeof(int16_t)<2 !!\n" ); nb_err++; } if (sizeof(uint8_t)!=1) { printf( "ERROR: sizeof(uint8_t)!=1 !!\n" ); nb_err++; } if (sizeof(int8_t)!=1) { printf( "ERROR: sizeof(int8_t)!=1 !!\n" ); nb_err++; } if (sizeof(uint32_t)<4) { printf( "ERROR: sizeof(uint32_t)<4 !!\n" ); nb_err++; } if (sizeof(int32_t)<4) { printf( "ERROR: sizeof(int32_t)<4 !!\n" ); nb_err++; } /* yes, i know, this test is silly. But better be safe than sorry. :) */ for(v=1000; v>=0; v--) { if ( (v>>2) != v/4) nb_err++; } for(v=-1000; v!=-1; v++) { if ( (v>>2) != (v/4)-!!(v%4)) nb_err++; } if (nb_err!=0) { printf( "ERROR! please post your platform/compiler specs to xvid-devel@xvid.org !\n" ); }}/********************************************************************* * main *********************************************************************/static void arg_missing(const char *opt){ printf( "missing argument after option '%s'\n", opt); exit(-1);}int main(int argc, const char *argv[]){ int c, what = 0; int width, height; uint32_t chksum = 0; const char * test_bitstream = 0; cpu_mask = 0; // default => will use autodectect for(c=1; c<argc; ++c) { if (!strcmp(argv[c], "-v")) verbose++; else if (!strcmp(argv[c], "-c")) cpu_mask = 0 /* PLAIN_C */ | XVID_CPU_FORCE; else if (!strcmp(argv[c], "-mmx")) cpu_mask = XVID_CPU_MMX | XVID_CPU_FORCE; else if (!strcmp(argv[c], "-mmxext")) cpu_mask = XVID_CPU_MMXEXT | XVID_CPU_MMX | XVID_CPU_FORCE; else if (!strcmp(argv[c], "-sse2")) cpu_mask = XVID_CPU_SSE2 | XVID_CPU_MMXEXT | XVID_CPU_MMX | XVID_CPU_FORCE; else if (!strcmp(argv[c], "-3dnow")) cpu_mask = XVID_CPU_3DNOW | XVID_CPU_FORCE; else if (!strcmp(argv[c], "-3dnowe")) cpu_mask = XVID_CPU_3DNOW | XVID_CPU_3DNOWEXT | XVID_CPU_FORCE; else if (!strcmp(argv[c], "-altivec")) cpu_mask = XVID_CPU_ALTIVEC | XVID_CPU_FORCE; else if (!strcmp(argv[c], "-spd")) { if (++c==argc) arg_missing( argv[argc-1] ); speed_ref = atoi(argv[c]); } else if (argv[c][0]!='-') { what = atoi(argv[c]); if (what==9) { if (c+4>argc) { printf("usage: %s %d bitstream width height (checksum)\n", argv[0], what); exit(-1); } test_bitstream = argv[++c]; width = atoi(argv[++c]); height = atoi(argv[++c]); if (c+1<argc && argv[c+1][0]!='-') { if (sscanf(argv[c+1], "0x%x", &chksum)!=1) { printf( "can't read checksum value.\n" ); exit(-1); } else c++; }// printf( "[%s] %dx%d (0x%.8x)\n", test_bitstream, width, height, chksum); } } else { printf( "unrecognized option '%s'\n", argv[c]); exit(-1); } } if (what==0 || what==1) test_dct(); if (what==0 || what==2) test_mb(); if (what==0 || what==3) test_sad(); if (what==0 || what==4) test_transfer(); if (what==0 || what==5) test_quant(); if (what==0 || what==6) test_cbp(); if (what==0 || what==10) test_sse(); if (what==0 || what==11) test_log2bin(); if (what==0 || what==12) test_gcd(); if (what==0 || what==13) test_compiler(); if (what==7) { test_IEEE1180_compliance(-256, 255, 1); test_IEEE1180_compliance(-256, 255,-1); test_IEEE1180_compliance( -5, 5, 1); test_IEEE1180_compliance( -5, 5,-1); test_IEEE1180_compliance(-300, 300, 1); test_IEEE1180_compliance(-300, 300,-1); } if (what==8) test_dct_saturation(-256, 255); if (test_bitstream) test_dec(test_bitstream, width, height, chksum); if (what==-1) { test_dct_precision_diffs(); test_bugs1(); } if (what==-2) test_quant_bug(); if ((what >= 0 && what <= 6) || what == 10) { printf("\n\n" "NB: If a function isn't optimised for a specific set of intructions,\n" " a C function is used instead. So don't panic if some functions\n" " may appear to be slow.\n"); }#ifdef ARCH_IS_IA32 if (what == 0 || what == 5) { printf("\n" "NB: MMX mpeg4 quantization is known to have very small errors (+/-1 magnitude)\n" " for 1 or 2 coefficients a block. This is mainly caused by the fact the unit\n" " test goes far behind the usual limits of real encoding. Please do not report\n" " this error to the developers.\n"); }#endif return 0;}/*********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -