diff options
author | Clément Bœsch <clement@stupeflix.com> | 2016-06-22 13:44:29 +0200 |
---|---|---|
committer | Clément Bœsch <clement@stupeflix.com> | 2016-06-22 13:44:34 +0200 |
commit | 5d48e4eafa6c4559683892b8638d10508125f3cf (patch) | |
tree | 0d5becbd08d6ae319497dd32cbe9b67f4670cc5e /libavcodec/tests | |
parent | 989a614b707dcff8abdffe28dc24ec64a83b2837 (diff) | |
parent | a6a750c7ef240b72ce01e9653343a0ddf247d196 (diff) | |
download | ffmpeg-5d48e4eafa6c4559683892b8638d10508125f3cf.tar.gz |
Merge commit 'a6a750c7ef240b72ce01e9653343a0ddf247d196'
* commit 'a6a750c7ef240b72ce01e9653343a0ddf247d196':
tests: Move all test programs to a subdirectory
Merged-by: Clément Bœsch <clement@stupeflix.com>
Diffstat (limited to 'libavcodec/tests')
-rw-r--r-- | libavcodec/tests/.gitignore | 16 | ||||
-rw-r--r-- | libavcodec/tests/arm/dct.c | 40 | ||||
-rw-r--r-- | libavcodec/tests/avfft.c | 53 | ||||
-rw-r--r-- | libavcodec/tests/cabac.c | 165 | ||||
-rw-r--r-- | libavcodec/tests/dct.c | 523 | ||||
-rw-r--r-- | libavcodec/tests/fft-fixed.c | 20 | ||||
-rw-r--r-- | libavcodec/tests/fft-fixed32.c | 21 | ||||
-rw-r--r-- | libavcodec/tests/fft.c | 519 | ||||
-rw-r--r-- | libavcodec/tests/golomb.c | 99 | ||||
-rw-r--r-- | libavcodec/tests/iirfilter.c | 54 | ||||
-rw-r--r-- | libavcodec/tests/imgconvert.c | 50 | ||||
-rw-r--r-- | libavcodec/tests/jpeg2000dwt.c | 141 | ||||
-rw-r--r-- | libavcodec/tests/mathops.c | 41 | ||||
-rw-r--r-- | libavcodec/tests/motion.c | 152 | ||||
-rw-r--r-- | libavcodec/tests/options.c | 194 | ||||
-rw-r--r-- | libavcodec/tests/ppc/dct.c | 32 | ||||
-rw-r--r-- | libavcodec/tests/rangecoder.c | 64 | ||||
-rw-r--r-- | libavcodec/tests/snowenc.c | 147 | ||||
-rw-r--r-- | libavcodec/tests/utils.c | 37 | ||||
-rw-r--r-- | libavcodec/tests/x86/dct.c | 133 |
20 files changed, 2501 insertions, 0 deletions
diff --git a/libavcodec/tests/.gitignore b/libavcodec/tests/.gitignore new file mode 100644 index 0000000000..d8ab947abe --- /dev/null +++ b/libavcodec/tests/.gitignore @@ -0,0 +1,16 @@ +/avfft +/cabac +/dct +/fft +/fft-fixed +/fft-fixed32 +/golomb +/iirfilter +/imgconvert +/jpeg2000dwt +/mathops +/motion +/options +/rangecoder +/snowenc +/utils diff --git a/libavcodec/tests/arm/dct.c b/libavcodec/tests/arm/dct.c new file mode 100644 index 0000000000..596d369a99 --- /dev/null +++ b/libavcodec/tests/arm/dct.c @@ -0,0 +1,40 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavcodec/arm/idct.h" + +static const struct algo fdct_tab_arch[] = { + { 0 } +}; + +static const struct algo idct_tab_arch[] = { + { "SIMPLE-ARM", ff_simple_idct_arm, FF_IDCT_PERM_NONE }, + { "INT-ARM", ff_j_rev_dct_arm, FF_IDCT_PERM_LIBMPEG2 }, +#if HAVE_ARMV5TE + { "SIMPLE-ARMV5TE", ff_simple_idct_armv5te, FF_IDCT_PERM_NONE, AV_CPU_FLAG_ARMV5TE }, +#endif +#if HAVE_ARMV6 + { "SIMPLE-ARMV6", ff_simple_idct_armv6, FF_IDCT_PERM_LIBMPEG2, AV_CPU_FLAG_ARMV6 }, +#endif +#if HAVE_NEON + { "SIMPLE-NEON", ff_simple_idct_neon, FF_IDCT_PERM_PARTTRANS, AV_CPU_FLAG_NEON }, +#endif + { 0 } +}; diff --git a/libavcodec/tests/avfft.c b/libavcodec/tests/avfft.c new file mode 100644 index 0000000000..6bc48ea870 --- /dev/null +++ b/libavcodec/tests/avfft.c @@ -0,0 +1,53 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/mem.h" +#include "libavcodec/avfft.h" + +int main(int argc, char **argv) +{ + int i; +#define LEN 1024 + FFTSample *ref = av_malloc_array(LEN, sizeof(*ref)); + FFTSample *data = av_malloc_array(LEN, sizeof(*data)); + RDFTContext *rdft_context = av_rdft_init(10, DFT_R2C); + RDFTContext *irdft_context = av_rdft_init(10, IDFT_C2R); + + if (!ref || !data || !rdft_context || !irdft_context) + return 2; + for (i=0; i<LEN; i++) { + ref[i] = data[i] = i*456 + 123 + i*i; + } + av_rdft_calc(rdft_context, data); + av_rdft_calc(irdft_context, data); + + for (i=0; i<LEN; i++) { + if (fabs(ref[i] - data[i]/LEN*2) > 1) { + fprintf(stderr, "Failed at %d (%f %f)\n", i, ref[i], data[i]/LEN*2); + return 1; + } + } + + av_rdft_end(rdft_context); + av_rdft_end(irdft_context); + av_free(data); + av_free(ref); + + return 0; +} diff --git a/libavcodec/tests/cabac.c b/libavcodec/tests/cabac.c new file mode 100644 index 0000000000..affe4eb141 --- /dev/null +++ b/libavcodec/tests/cabac.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/cabac.c" + +#define SIZE 10240 + +#include "libavutil/lfg.h" +#include "libavcodec/avcodec.h" + +static inline void put_cabac_bit(CABACContext *c, int b){ + put_bits(&c->pb, 1, b); + for(;c->outstanding_count; c->outstanding_count--){ + put_bits(&c->pb, 1, 1-b); + } +} + +static inline void renorm_cabac_encoder(CABACContext *c){ + while(c->range < 0x100){ + //FIXME optimize + if(c->low<0x100){ + put_cabac_bit(c, 0); + }else if(c->low<0x200){ + c->outstanding_count++; + c->low -= 0x100; + }else{ + put_cabac_bit(c, 1); + c->low -= 0x200; + } + + c->range+= c->range; + c->low += c->low; + } +} + +static void put_cabac(CABACContext *c, uint8_t * const state, int bit){ + int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state]; + + if(bit == ((*state)&1)){ + c->range -= RangeLPS; + *state = ff_h264_mlps_state[128 + *state]; + }else{ + c->low += c->range - RangeLPS; + c->range = RangeLPS; + *state= ff_h264_mlps_state[127 - *state]; + } + + renorm_cabac_encoder(c); +} + +/** + * @param bit 0 -> write zero bit, !=0 write one bit + */ +static void put_cabac_bypass(CABACContext *c, int bit){ + c->low += c->low; + + if(bit){ + c->low += c->range; + } +//FIXME optimize + if(c->low<0x200){ + put_cabac_bit(c, 0); + }else if(c->low<0x400){ + c->outstanding_count++; + c->low -= 0x200; + }else{ + put_cabac_bit(c, 1); + c->low -= 0x400; + } +} + +/** + * + * @return the number of bytes written + */ +static int put_cabac_terminate(CABACContext *c, int bit){ + c->range -= 2; + + if(!bit){ + renorm_cabac_encoder(c); + }else{ + c->low += c->range; + c->range= 2; + + renorm_cabac_encoder(c); + + av_assert0(c->low <= 0x1FF); + put_cabac_bit(c, c->low>>9); + put_bits(&c->pb, 2, ((c->low>>7)&3)|1); + + flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong + } + + return (put_bits_count(&c->pb)+7)>>3; +} + +int main(void){ + CABACContext c; + uint8_t b[9*SIZE]; + uint8_t r[9*SIZE]; + int i, ret = 0; + uint8_t state[10]= {0}; + AVLFG prng; + + av_lfg_init(&prng, 1); + ff_init_cabac_encoder(&c, b, SIZE); + + for(i=0; i<SIZE; i++){ + if(2*i<SIZE) r[i] = av_lfg_get(&prng) % 7; + else r[i] = (i>>8)&1; + } + + for(i=0; i<SIZE; i++){ + put_cabac_bypass(&c, r[i]&1); + } + + for(i=0; i<SIZE; i++){ + put_cabac(&c, state, r[i]&1); + } + + i= put_cabac_terminate(&c, 1); + b[i++] = av_lfg_get(&prng); + b[i ] = av_lfg_get(&prng); + + ff_init_cabac_decoder(&c, b, SIZE); + + memset(state, 0, sizeof(state)); + + for(i=0; i<SIZE; i++){ + if( (r[i]&1) != get_cabac_bypass(&c) ) { + av_log(NULL, AV_LOG_ERROR, "CABAC bypass failure at %d\n", i); + ret = 1; + } + } + + for(i=0; i<SIZE; i++){ + if( (r[i]&1) != get_cabac_noinline(&c, state) ) { + av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i); + ret = 1; + } + } + if(!get_cabac_terminate(&c)) { + av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n"); + ret = 1; + } + + return ret; +} diff --git a/libavcodec/tests/dct.c b/libavcodec/tests/dct.c new file mode 100644 index 0000000000..5303fdff8f --- /dev/null +++ b/libavcodec/tests/dct.c @@ -0,0 +1,523 @@ +/* + * (c) 2001 Fabrice Bellard + * 2007 Marc Hoffman <marc.hoffman@analog.com> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * DCT test (c) 2001 Fabrice Bellard + * Started from sample code by Juan J. Sierralta P. + */ + +#include "config.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <math.h> + +#include "libavutil/cpu.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/lfg.h" +#include "libavutil/time.h" + +#include "libavcodec/dct.h" +#include "libavcodec/idctdsp.h" +#include "libavcodec/simple_idct.h" +#include "libavcodec/xvididct.h" +#include "libavcodec/aandcttab.h" +#include "libavcodec/faandct.h" +#include "libavcodec/faanidct.h" +#include "libavcodec/dctref.h" + +struct algo { + const char *name; + void (*func)(int16_t *block); + enum idct_permutation_type perm_type; + int cpu_flag; + int nonspec; +}; + +static const struct algo fdct_tab[] = { + { "REF-DBL", ff_ref_fdct, FF_IDCT_PERM_NONE }, + { "IJG-AAN-INT", ff_fdct_ifast, FF_IDCT_PERM_NONE }, + { "IJG-LLM-INT", ff_jpeg_fdct_islow_8, FF_IDCT_PERM_NONE }, +#if CONFIG_FAANDCT + { "FAAN", ff_faandct, FF_IDCT_PERM_NONE }, +#endif /* CONFIG_FAANDCT */ +}; + +static void ff_prores_idct_wrap(int16_t *dst){ + LOCAL_ALIGNED(16, int16_t, qmat, [64]); + int i; + + for(i=0; i<64; i++){ + qmat[i]=4; + } + ff_prores_idct(dst, qmat); + for(i=0; i<64; i++) { + dst[i] -= 512; + } +} + +static const struct algo idct_tab[] = { + { "REF-DBL", ff_ref_idct, FF_IDCT_PERM_NONE }, + { "INT", ff_j_rev_dct, FF_IDCT_PERM_LIBMPEG2 }, + { "SIMPLE-C", ff_simple_idct_8, FF_IDCT_PERM_NONE }, + { "SIMPLE-C10", ff_simple_idct_10, FF_IDCT_PERM_NONE }, + { "SIMPLE-C12", ff_simple_idct_12, FF_IDCT_PERM_NONE, 0, 1 }, + { "PR-C", ff_prores_idct_wrap, FF_IDCT_PERM_NONE, 0, 1 }, +#if CONFIG_FAANIDCT + { "FAANI", ff_faanidct, FF_IDCT_PERM_NONE }, +#endif /* CONFIG_FAANIDCT */ +#if CONFIG_MPEG4_DECODER + { "XVID", ff_xvid_idct, FF_IDCT_PERM_NONE, 0, 1 }, +#endif /* CONFIG_MPEG4_DECODER */ +}; + +#if ARCH_ARM +#include "arm/dct.c" +#elif ARCH_PPC +#include "ppc/dct.c" +#elif ARCH_X86 +#include "x86/dct.c" +#else +static const struct algo fdct_tab_arch[] = { { 0 } }; +static const struct algo idct_tab_arch[] = { { 0 } }; +#endif + +#define AANSCALE_BITS 12 + +#define NB_ITS 20000 +#define NB_ITS_SPEED 50000 + +DECLARE_ALIGNED(16, static int16_t, block)[64]; +DECLARE_ALIGNED(8, static int16_t, block1)[64]; + +static void init_block(int16_t block[64], int test, int is_idct, AVLFG *prng, int vals) +{ + int i, j; + + memset(block, 0, 64 * sizeof(*block)); + + switch (test) { + case 0: + for (i = 0; i < 64; i++) + block[i] = (av_lfg_get(prng) % (2*vals)) -vals; + if (is_idct) { + ff_ref_fdct(block); + for (i = 0; i < 64; i++) + block[i] >>= 3; + } + break; + case 1: + j = av_lfg_get(prng) % 10 + 1; + for (i = 0; i < j; i++) { + int idx = av_lfg_get(prng) % 64; + block[idx] = av_lfg_get(prng) % (2*vals) -vals; + } + break; + case 2: + block[ 0] = av_lfg_get(prng) % (16*vals) - (8*vals); + block[63] = (block[0] & 1) ^ 1; + break; + } +} + +static void permute(int16_t dst[64], const int16_t src[64], + enum idct_permutation_type perm_type) +{ + int i; + +#if ARCH_X86 + if (permute_x86(dst, src, perm_type)) + return; +#endif + + switch (perm_type) { + case FF_IDCT_PERM_LIBMPEG2: + for (i = 0; i < 64; i++) + dst[(i & 0x38) | ((i & 6) >> 1) | ((i & 1) << 2)] = src[i]; + break; + case FF_IDCT_PERM_PARTTRANS: + for (i = 0; i < 64; i++) + dst[(i & 0x24) | ((i & 3) << 3) | ((i >> 3) & 3)] = src[i]; + break; + case FF_IDCT_PERM_TRANSPOSE: + for (i = 0; i < 64; i++) + dst[(i>>3) | ((i<<3)&0x38)] = src[i]; + break; + default: + for (i = 0; i < 64; i++) + dst[i] = src[i]; + break; + } +} + +static int dct_error(const struct algo *dct, int test, int is_idct, int speed, const int bits) +{ + void (*ref)(int16_t *block) = is_idct ? ff_ref_idct : ff_ref_fdct; + int it, i, scale; + int err_inf, v; + int64_t err2, ti, ti1, it1, err_sum = 0; + int64_t sysErr[64], sysErrMax = 0; + int maxout = 0; + int blockSumErrMax = 0, blockSumErr; + AVLFG prng; + const int vals=1<<bits; + double omse, ome; + int spec_err; + + av_lfg_init(&prng, 1); + + err_inf = 0; + err2 = 0; + for (i = 0; i < 64; i++) + sysErr[i] = 0; + for (it = 0; it < NB_ITS; it++) { + init_block(block1, test, is_idct, &prng, vals); + permute(block, block1, dct->perm_type); + + dct->func(block); + emms_c(); + + if (!strcmp(dct->name, "IJG-AAN-INT")) { + for (i = 0; i < 64; i++) { + scale = 8 * (1 << (AANSCALE_BITS + 11)) / ff_aanscales[i]; + block[i] = (block[i] * scale) >> AANSCALE_BITS; + } + } + + ref(block1); + if (!strcmp(dct->name, "PR-SSE2")) + for (i = 0; i < 64; i++) + block1[i] = av_clip(block1[i], 4-512, 1019-512); + + blockSumErr = 0; + for (i = 0; i < 64; i++) { + int err = block[i] - block1[i]; + err_sum += err; + v = abs(err); + if (v > err_inf) + err_inf = v; + err2 += v * v; + sysErr[i] += block[i] - block1[i]; + blockSumErr += v; + if (abs(block[i]) > maxout) + maxout = abs(block[i]); + } + if (blockSumErrMax < blockSumErr) + blockSumErrMax = blockSumErr; + } + for (i = 0; i < 64; i++) + sysErrMax = FFMAX(sysErrMax, FFABS(sysErr[i])); + + for (i = 0; i < 64; i++) { + if (i % 8 == 0) + printf("\n"); + printf("%7d ", (int) sysErr[i]); + } + printf("\n"); + + omse = (double) err2 / NB_ITS / 64; + ome = (double) err_sum / NB_ITS / 64; + + spec_err = is_idct && (err_inf > 1 || omse > 0.02 || fabs(ome) > 0.0015); + + printf("%s %s: max_err=%d omse=%0.8f ome=%0.8f syserr=%0.8f maxout=%d blockSumErr=%d\n", + is_idct ? "IDCT" : "DCT", dct->name, err_inf, + omse, ome, (double) sysErrMax / NB_ITS, + maxout, blockSumErrMax); + + if (spec_err && !dct->nonspec) { + printf("Failed!\n"); + return 1; + } + + if (!speed) + return 0; + + /* speed test */ + + init_block(block, test, is_idct, &prng, vals); + permute(block1, block, dct->perm_type); + + ti = av_gettime_relative(); + it1 = 0; + do { + for (it = 0; it < NB_ITS_SPEED; it++) { + memcpy(block, block1, sizeof(block)); + dct->func(block); + } + emms_c(); + it1 += NB_ITS_SPEED; + ti1 = av_gettime_relative() - ti; + } while (ti1 < 1000000); + + printf("%s %s: %0.1f kdct/s\n", is_idct ? "IDCT" : "DCT", dct->name, + (double) it1 * 1000.0 / (double) ti1); + + return 0; +} + +DECLARE_ALIGNED(8, static uint8_t, img_dest)[64]; +DECLARE_ALIGNED(8, static uint8_t, img_dest1)[64]; + +static void idct248_ref(uint8_t *dest, int linesize, int16_t *block) +{ + static int init; + static double c8[8][8]; + static double c4[4][4]; + double block1[64], block2[64], block3[64]; + double s, sum, v; + int i, j, k; + + if (!init) { + init = 1; + + for (i = 0; i < 8; i++) { + sum = 0; + for (j = 0; j < 8; j++) { + s = (i == 0) ? sqrt(1.0 / 8.0) : sqrt(1.0 / 4.0); + c8[i][j] = s * cos(M_PI * i * (j + 0.5) / 8.0); + sum += c8[i][j] * c8[i][j]; + } + } + + for (i = 0; i < 4; i++) { + sum = 0; + for (j = 0; j < 4; j++) { + s = (i == 0) ? sqrt(1.0 / 4.0) : sqrt(1.0 / 2.0); + c4[i][j] = s * cos(M_PI * i * (j + 0.5) / 4.0); + sum += c4[i][j] * c4[i][j]; + } + } + } + + /* butterfly */ + s = 0.5 * sqrt(2.0); + for (i = 0; i < 4; i++) { + for (j = 0; j < 8; j++) { + block1[8 * (2 * i) + j] = + (block[8 * (2 * i) + j] + block[8 * (2 * i + 1) + j]) * s; + block1[8 * (2 * i + 1) + j] = + (block[8 * (2 * i) + j] - block[8 * (2 * i + 1) + j]) * s; + } + } + + /* idct8 on lines */ + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + sum = 0; + for (k = 0; k < 8; k++) + sum += c8[k][j] * block1[8 * i + k]; + block2[8 * i + j] = sum; + } + } + + /* idct4 */ + for (i = 0; i < 8; i++) { + for (j = 0; j < 4; j++) { + /* top */ + sum = 0; + for (k = 0; k < 4; k++) + sum += c4[k][j] * block2[8 * (2 * k) + i]; + block3[8 * (2 * j) + i] = sum; + + /* bottom */ + sum = 0; + for (k = 0; k < 4; k++) + sum += c4[k][j] * block2[8 * (2 * k + 1) + i]; + block3[8 * (2 * j + 1) + i] = sum; + } + } + + /* clamp and store the result */ + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + v = block3[8 * i + j]; + if (v < 0) v = 0; + else if (v > 255) v = 255; + dest[i * linesize + j] = (int) rint(v); + } + } +} + +static void idct248_error(const char *name, + void (*idct248_put)(uint8_t *dest, int line_size, + int16_t *block), + int speed) +{ + int it, i, it1, ti, ti1, err_max, v; + AVLFG prng; + + av_lfg_init(&prng, 1); + + /* just one test to see if code is correct (precision is less + important here) */ + err_max = 0; + for (it = 0; it < NB_ITS; it++) { + /* XXX: use forward transform to generate values */ + for (i = 0; i < 64; i++) + block1[i] = av_lfg_get(&prng) % 256 - 128; + block1[0] += 1024; + + for (i = 0; i < 64; i++) + block[i] = block1[i]; + idct248_ref(img_dest1, 8, block); + + for (i = 0; i < 64; i++) + block[i] = block1[i]; + idct248_put(img_dest, 8, block); + + for (i = 0; i < 64; i++) { + v = abs((int) img_dest[i] - (int) img_dest1[i]); + if (v == 255) + printf("%d %d\n", img_dest[i], img_dest1[i]); + if (v > err_max) + err_max = v; + } +#if 0 + printf("ref=\n"); + for(i=0;i<8;i++) { + int j; + for(j=0;j<8;j++) { + printf(" %3d", img_dest1[i*8+j]); + } + printf("\n"); + } + + printf("out=\n"); + for(i=0;i<8;i++) { + int j; + for(j=0;j<8;j++) { + printf(" %3d", img_dest[i*8+j]); + } + printf("\n"); + } +#endif + } + printf("%s %s: err_inf=%d\n", 1 ? "IDCT248" : "DCT248", name, err_max); + + if (!speed) + return; + + ti = av_gettime_relative(); + it1 = 0; + do { + for (it = 0; it < NB_ITS_SPEED; it++) { + for (i = 0; i < 64; i++) + block[i] = block1[i]; + idct248_put(img_dest, 8, block); + } + emms_c(); + it1 += NB_ITS_SPEED; + ti1 = av_gettime_relative() - ti; + } while (ti1 < 1000000); + + printf("%s %s: %0.1f kdct/s\n", 1 ? "IDCT248" : "DCT248", name, + (double) it1 * 1000.0 / (double) ti1); +} + +static void help(void) +{ + printf("dct-test [-i] [<test-number>] [<bits>]\n" + "test-number 0 -> test with random matrixes\n" + " 1 -> test with random sparse matrixes\n" + " 2 -> do 3. test from MPEG-4 std\n" + "bits Number of time domain bits to use, 8 is default\n" + "-i test IDCT implementations\n" + "-4 test IDCT248 implementations\n" + "-t speed test\n"); +} + +#if !HAVE_GETOPT +#include "compat/getopt.c" +#endif + +int main(int argc, char **argv) +{ + int test_idct = 0, test_248_dct = 0; + int c, i; + int test = 1; + int speed = 0; + int err = 0; + int bits=8; + + ff_ref_dct_init(); + + for (;;) { + c = getopt(argc, argv, "ih4t"); + if (c == -1) + break; + switch (c) { + case 'i': + test_idct = 1; + break; + case '4': + test_248_dct = 1; + break; + case 't': + speed = 1; + break; + default: + case 'h': + help(); + return 0; + } + } + + if (optind < argc) + test = atoi(argv[optind]); + if(optind+1 < argc) bits= atoi(argv[optind+1]); + + printf("ffmpeg DCT/IDCT test\n"); + + if (test_248_dct) { + idct248_error("SIMPLE-C", ff_simple_idct248_put, speed); + } else { + const int cpu_flags = av_get_cpu_flags(); + if (test_idct) { + for (i = 0; i < FF_ARRAY_ELEMS(idct_tab); i++) + err |= dct_error(&idct_tab[i], test, test_idct, speed, bits); + + for (i = 0; idct_tab_arch[i].name; i++) + if (!(~cpu_flags & idct_tab_arch[i].cpu_flag)) + err |= dct_error(&idct_tab_arch[i], test, test_idct, speed, bits); + } +#if CONFIG_FDCTDSP + else { + for (i = 0; i < FF_ARRAY_ELEMS(fdct_tab); i++) + err |= dct_error(&fdct_tab[i], test, test_idct, speed, bits); + + for (i = 0; fdct_tab_arch[i].name; i++) + if (!(~cpu_flags & fdct_tab_arch[i].cpu_flag)) + err |= dct_error(&fdct_tab_arch[i], test, test_idct, speed, bits); + } +#endif /* CONFIG_FDCTDSP */ + } + + if (err) + printf("Error: %d.\n", err); + + return !!err; +} diff --git a/libavcodec/tests/fft-fixed.c b/libavcodec/tests/fft-fixed.c new file mode 100644 index 0000000000..fe1b57a3f6 --- /dev/null +++ b/libavcodec/tests/fft-fixed.c @@ -0,0 +1,20 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define FFT_FLOAT 0 +#include "fft.c" diff --git a/libavcodec/tests/fft-fixed32.c b/libavcodec/tests/fft-fixed32.c new file mode 100644 index 0000000000..f33494f7f3 --- /dev/null +++ b/libavcodec/tests/fft-fixed32.c @@ -0,0 +1,21 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define FFT_FLOAT 0 +#define FFT_FIXED_32 1 +#include "fft.c" diff --git a/libavcodec/tests/fft.c b/libavcodec/tests/fft.c new file mode 100644 index 0000000000..4717303155 --- /dev/null +++ b/libavcodec/tests/fft.c @@ -0,0 +1,519 @@ +/* + * (c) 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * FFT and MDCT tests. + */ + +#include "config.h" + +#include <math.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "libavutil/cpu.h" +#include "libavutil/lfg.h" +#include "libavutil/log.h" +#include "libavutil/mathematics.h" +#include "libavutil/time.h" + +#include "libavcodec/fft.h" +#if FFT_FLOAT +#include "libavcodec/dct.h" +#include "libavcodec/rdft.h" +#endif + +/* reference fft */ + +#define MUL16(a, b) ((a) * (b)) + +#define CMAC(pre, pim, are, aim, bre, bim) \ + { \ + pre += (MUL16(are, bre) - MUL16(aim, bim)); \ + pim += (MUL16(are, bim) + MUL16(bre, aim)); \ + } + +#if FFT_FLOAT +#define RANGE 1.0 +#define REF_SCALE(x, bits) (x) +#define FMT "%10.6f" +#elif FFT_FIXED_32 +#define RANGE 8388608 +#define REF_SCALE(x, bits) (x) +#define FMT "%6d" +#else +#define RANGE 16384 +#define REF_SCALE(x, bits) ((x) / (1 << (bits))) +#define FMT "%6d" +#endif + +static struct { + float re, im; +} *exptab; + +static int fft_ref_init(int nbits, int inverse) +{ + int i, n = 1 << nbits; + + exptab = av_malloc_array((n / 2), sizeof(*exptab)); + if (!exptab) + return AVERROR(ENOMEM); + + for (i = 0; i < (n / 2); i++) { + double alpha = 2 * M_PI * (float) i / (float) n; + double c1 = cos(alpha), s1 = sin(alpha); + if (!inverse) + s1 = -s1; + exptab[i].re = c1; + exptab[i].im = s1; + } + return 0; +} + +static void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits) +{ + int i, j; + int n = 1 << nbits; + int n2 = n >> 1; + + for (i = 0; i < n; i++) { + double tmp_re = 0, tmp_im = 0; + FFTComplex *q = tab; + for (j = 0; j < n; j++) { + double s, c; + int k = (i * j) & (n - 1); + if (k >= n2) { + c = -exptab[k - n2].re; + s = -exptab[k - n2].im; + } else { + c = exptab[k].re; + s = exptab[k].im; + } + CMAC(tmp_re, tmp_im, c, s, q->re, q->im); + q++; + } + tabr[i].re = REF_SCALE(tmp_re, nbits); + tabr[i].im = REF_SCALE(tmp_im, nbits); + } +} + +#if CONFIG_MDCT +static void imdct_ref(FFTSample *out, FFTSample *in, int nbits) +{ + int i, k, n = 1 << nbits; + + for (i = 0; i < n; i++) { + double sum = 0; + for (k = 0; k < n / 2; k++) { + int a = (2 * i + 1 + (n / 2)) * (2 * k + 1); + double f = cos(M_PI * a / (double) (2 * n)); + sum += f * in[k]; + } + out[i] = REF_SCALE(-sum, nbits - 2); + } +} + +/* NOTE: no normalisation by 1 / N is done */ +static void mdct_ref(FFTSample *output, FFTSample *input, int nbits) +{ + int i, k, n = 1 << nbits; + + /* do it by hand */ + for (k = 0; k < n / 2; k++) { + double s = 0; + for (i = 0; i < n; i++) { + double a = (2 * M_PI * (2 * i + 1 + n / 2) * (2 * k + 1) / (4 * n)); + s += input[i] * cos(a); + } + output[k] = REF_SCALE(s, nbits - 1); + } +} +#endif /* CONFIG_MDCT */ + +#if FFT_FLOAT +#if CONFIG_DCT +static void idct_ref(FFTSample *output, FFTSample *input, int nbits) +{ + int i, k, n = 1 << nbits; + + /* do it by hand */ + for (i = 0; i < n; i++) { + double s = 0.5 * input[0]; + for (k = 1; k < n; k++) { + double a = M_PI * k * (i + 0.5) / n; + s += input[k] * cos(a); + } + output[i] = 2 * s / n; + } +} + +static void dct_ref(FFTSample *output, FFTSample *input, int nbits) +{ + int i, k, n = 1 << nbits; + + /* do it by hand */ + for (k = 0; k < n; k++) { + double s = 0; + for (i = 0; i < n; i++) { + double a = M_PI * k * (i + 0.5) / n; + s += input[i] * cos(a); + } + output[k] = s; + } +} +#endif /* CONFIG_DCT */ +#endif /* FFT_FLOAT */ + +static FFTSample frandom(AVLFG *prng) +{ + return (int16_t) av_lfg_get(prng) / 32768.0 * RANGE; +} + +static int check_diff(FFTSample *tab1, FFTSample *tab2, int n, double scale) +{ + int i, err = 0; + double error = 0, max = 0; + + for (i = 0; i < n; i++) { + double e = fabs(tab1[i] - (tab2[i] / scale)) / RANGE; + if (e >= 1e-3) { + av_log(NULL, AV_LOG_ERROR, "ERROR %5d: "FMT" "FMT"\n", + i, tab1[i], tab2[i]); + err = 1; + } + error += e * e; + if (e > max) + max = e; + } + av_log(NULL, AV_LOG_INFO, "max:%f e:%g\n", max, sqrt(error / n)); + return err; +} + +static void help(void) +{ + av_log(NULL, AV_LOG_INFO, + "usage: fft-test [-h] [-s] [-i] [-n b]\n" + "-h print this help\n" + "-s speed test\n" + "-m (I)MDCT test\n" + "-d (I)DCT test\n" + "-r (I)RDFT test\n" + "-i inverse transform test\n" + "-n b set the transform size to 2^b\n" + "-f x set scale factor for output data of (I)MDCT to x\n"); +} + +enum tf_transform { + TRANSFORM_FFT, + TRANSFORM_MDCT, + TRANSFORM_RDFT, + TRANSFORM_DCT, +}; + +#if !HAVE_GETOPT +#include "compat/getopt.c" +#endif + +int main(int argc, char **argv) +{ + FFTComplex *tab, *tab1, *tab_ref; + FFTSample *tab2; + enum tf_transform transform = TRANSFORM_FFT; + FFTContext m, s; +#if FFT_FLOAT + RDFTContext r; + DCTContext d; +#endif /* FFT_FLOAT */ + int it, i, err = 1; + int do_speed = 0, do_inverse = 0; + int fft_nbits = 9, fft_size; + double scale = 1.0; + AVLFG prng; + + av_lfg_init(&prng, 1); + + for (;;) { + int c = getopt(argc, argv, "hsimrdn:f:c:"); + if (c == -1) + break; + switch (c) { + case 'h': + help(); + return 1; + case 's': + do_speed = 1; + break; + case 'i': + do_inverse = 1; + break; + case 'm': + transform = TRANSFORM_MDCT; + break; + case 'r': + transform = TRANSFORM_RDFT; + break; + case 'd': + transform = TRANSFORM_DCT; + break; + case 'n': + fft_nbits = atoi(optarg); + break; + case 'f': + scale = atof(optarg); + break; + case 'c': + { + unsigned cpuflags = av_get_cpu_flags(); + + if (av_parse_cpu_caps(&cpuflags, optarg) < 0) + return 1; + + av_force_cpu_flags(cpuflags); + break; + } + } + } + + fft_size = 1 << fft_nbits; + tab = av_malloc_array(fft_size, sizeof(FFTComplex)); + tab1 = av_malloc_array(fft_size, sizeof(FFTComplex)); + tab_ref = av_malloc_array(fft_size, sizeof(FFTComplex)); + tab2 = av_malloc_array(fft_size, sizeof(FFTSample)); + + if (!(tab && tab1 && tab_ref && tab2)) + goto cleanup; + + switch (transform) { +#if CONFIG_MDCT + case TRANSFORM_MDCT: + av_log(NULL, AV_LOG_INFO, "Scale factor is set to %f\n", scale); + if (do_inverse) + av_log(NULL, AV_LOG_INFO, "IMDCT"); + else + av_log(NULL, AV_LOG_INFO, "MDCT"); + ff_mdct_init(&m, fft_nbits, do_inverse, scale); + break; +#endif /* CONFIG_MDCT */ + case TRANSFORM_FFT: + if (do_inverse) + av_log(NULL, AV_LOG_INFO, "IFFT"); + else + av_log(NULL, AV_LOG_INFO, "FFT"); + ff_fft_init(&s, fft_nbits, do_inverse); + if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) + goto cleanup; + break; +#if FFT_FLOAT +# if CONFIG_RDFT + case TRANSFORM_RDFT: + if (do_inverse) + av_log(NULL, AV_LOG_INFO, "IDFT_C2R"); + else + av_log(NULL, AV_LOG_INFO, "DFT_R2C"); + ff_rdft_init(&r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); + if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) + goto cleanup; + break; +# endif /* CONFIG_RDFT */ +# if CONFIG_DCT + case TRANSFORM_DCT: + if (do_inverse) + av_log(NULL, AV_LOG_INFO, "DCT_III"); + else + av_log(NULL, AV_LOG_INFO, "DCT_II"); + ff_dct_init(&d, fft_nbits, do_inverse ? DCT_III : DCT_II); + break; +# endif /* CONFIG_DCT */ +#endif /* FFT_FLOAT */ + default: + av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n"); + goto cleanup; + } + av_log(NULL, AV_LOG_INFO, " %d test\n", fft_size); + + /* generate random data */ + + for (i = 0; i < fft_size; i++) { + tab1[i].re = frandom(&prng); + tab1[i].im = frandom(&prng); + } + + /* checking result */ + av_log(NULL, AV_LOG_INFO, "Checking...\n"); + + switch (transform) { +#if CONFIG_MDCT + case TRANSFORM_MDCT: + if (do_inverse) { + imdct_ref(&tab_ref->re, &tab1->re, fft_nbits); + m.imdct_calc(&m, tab2, &tab1->re); + err = check_diff(&tab_ref->re, tab2, fft_size, scale); + } else { + mdct_ref(&tab_ref->re, &tab1->re, fft_nbits); + m.mdct_calc(&m, tab2, &tab1->re); + err = check_diff(&tab_ref->re, tab2, fft_size / 2, scale); + } + break; +#endif /* CONFIG_MDCT */ + case TRANSFORM_FFT: + memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); + s.fft_permute(&s, tab); + s.fft_calc(&s, tab); + + fft_ref(tab_ref, tab1, fft_nbits); + err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0); + break; +#if FFT_FLOAT +#if CONFIG_RDFT + case TRANSFORM_RDFT: + { + int fft_size_2 = fft_size >> 1; + if (do_inverse) { + tab1[0].im = 0; + tab1[fft_size_2].im = 0; + for (i = 1; i < fft_size_2; i++) { + tab1[fft_size_2 + i].re = tab1[fft_size_2 - i].re; + tab1[fft_size_2 + i].im = -tab1[fft_size_2 - i].im; + } + + memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); + tab2[1] = tab1[fft_size_2].re; + + r.rdft_calc(&r, tab2); + fft_ref(tab_ref, tab1, fft_nbits); + for (i = 0; i < fft_size; i++) { + tab[i].re = tab2[i]; + tab[i].im = 0; + } + err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 0.5); + } else { + for (i = 0; i < fft_size; i++) { + tab2[i] = tab1[i].re; + tab1[i].im = 0; + } + r.rdft_calc(&r, tab2); + fft_ref(tab_ref, tab1, fft_nbits); + tab_ref[0].im = tab_ref[fft_size_2].re; + err = check_diff(&tab_ref->re, tab2, fft_size, 1.0); + } + break; + } +#endif /* CONFIG_RDFT */ +#if CONFIG_DCT + case TRANSFORM_DCT: + memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); + d.dct_calc(&d, &tab->re); + if (do_inverse) + idct_ref(&tab_ref->re, &tab1->re, fft_nbits); + else + dct_ref(&tab_ref->re, &tab1->re, fft_nbits); + err = check_diff(&tab_ref->re, &tab->re, fft_size, 1.0); + break; +#endif /* CONFIG_DCT */ +#endif /* FFT_FLOAT */ + } + + /* do a speed test */ + + if (do_speed) { + int64_t time_start, duration; + int nb_its; + + av_log(NULL, AV_LOG_INFO, "Speed test...\n"); + /* we measure during about 1 seconds */ + nb_its = 1; + for (;;) { + time_start = av_gettime_relative(); + for (it = 0; it < nb_its; it++) { + switch (transform) { + case TRANSFORM_MDCT: + if (do_inverse) + m.imdct_calc(&m, &tab->re, &tab1->re); + else + m.mdct_calc(&m, &tab->re, &tab1->re); + break; + case TRANSFORM_FFT: + memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); + s.fft_calc(&s, tab); + break; +#if FFT_FLOAT + case TRANSFORM_RDFT: + memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); + r.rdft_calc(&r, tab2); + break; + case TRANSFORM_DCT: + memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); + d.dct_calc(&d, tab2); + break; +#endif /* FFT_FLOAT */ + } + } + duration = av_gettime_relative() - time_start; + if (duration >= 1000000) + break; + nb_its *= 2; + } + av_log(NULL, AV_LOG_INFO, + "time: %0.1f us/transform [total time=%0.2f s its=%d]\n", + (double) duration / nb_its, + (double) duration / 1000000.0, + nb_its); + } + + switch (transform) { +#if CONFIG_MDCT + case TRANSFORM_MDCT: + ff_mdct_end(&m); + break; +#endif /* CONFIG_MDCT */ + case TRANSFORM_FFT: + ff_fft_end(&s); + break; +#if FFT_FLOAT +# if CONFIG_RDFT + case TRANSFORM_RDFT: + ff_rdft_end(&r); + break; +# endif /* CONFIG_RDFT */ +# if CONFIG_DCT + case TRANSFORM_DCT: + ff_dct_end(&d); + break; +# endif /* CONFIG_DCT */ +#endif /* FFT_FLOAT */ + } + +cleanup: + av_free(tab); + av_free(tab1); + av_free(tab2); + av_free(tab_ref); + av_free(exptab); + + if (err) + printf("Error: %d.\n", err); + + return !!err; +} diff --git a/libavcodec/tests/golomb.c b/libavcodec/tests/golomb.c new file mode 100644 index 0000000000..965367b7be --- /dev/null +++ b/libavcodec/tests/golomb.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdint.h> +#include <stdio.h> + +#include "libavutil/mem.h" + +#include "libavcodec/get_bits.h" +#include "libavcodec/golomb.h" +#include "libavcodec/put_bits.h" + +#define COUNT 8191 +#define SIZE (COUNT * 4) + +int main(void) +{ + int i, ret = 0; + uint8_t *temp; + PutBitContext pb; + GetBitContext gb; + + temp = av_malloc(SIZE); + if (!temp) + return 2; + + init_put_bits(&pb, temp, SIZE); + for (i = 0; i < COUNT; i++) + set_ue_golomb(&pb, i); + flush_put_bits(&pb); + + init_get_bits(&gb, temp, 8 * SIZE); + for (i = 0; i < COUNT; i++) { + int j, s = show_bits(&gb, 25); + + j = get_ue_golomb(&gb); + if (j != i) { + fprintf(stderr, "get_ue_golomb: expected %d, got %d. bits: %7x\n", + i, j, s); + ret = 1; + } + } + +#define EXTEND(i) ((i) << 3 | (i) & 7) + init_put_bits(&pb, temp, SIZE); + for (i = 0; i < COUNT; i++) + set_ue_golomb(&pb, EXTEND(i)); + flush_put_bits(&pb); + + init_get_bits(&gb, temp, 8 * SIZE); + for (i = 0; i < COUNT; i++) { + int j, s = show_bits_long(&gb, 32); + + j = get_ue_golomb_long(&gb); + if (j != EXTEND(i)) { + fprintf(stderr, "get_ue_golomb_long: expected %d, got %d. " + "bits: %8x\n", EXTEND(i), j, s); + ret = 1; + } + } + + init_put_bits(&pb, temp, SIZE); + for (i = 0; i < COUNT; i++) + set_se_golomb(&pb, i - COUNT / 2); + flush_put_bits(&pb); + + init_get_bits(&gb, temp, 8 * SIZE); + for (i = 0; i < COUNT; i++) { + int j, s = show_bits(&gb, 25); + + j = get_se_golomb(&gb); + if (j != i - COUNT / 2) { + fprintf(stderr, "get_se_golomb: expected %d, got %d. bits: %7x\n", + i - COUNT / 2, j, s); + ret = 1; + } + } + + av_free(temp); + + return ret; +} diff --git a/libavcodec/tests/iirfilter.c b/libavcodec/tests/iirfilter.c new file mode 100644 index 0000000000..60cc6fc43d --- /dev/null +++ b/libavcodec/tests/iirfilter.c @@ -0,0 +1,54 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> +#include <stdint.h> +#include <stdio.h> + +#include "libavutil/libm.h" + +#include "libavcodec/iirfilter.h" + +#define FILT_ORDER 4 +#define SIZE 1024 + +int main(void) +{ + struct FFIIRFilterCoeffs *fcoeffs = NULL; + struct FFIIRFilterState *fstate = NULL; + float cutoff_coeff = 0.4; + int16_t x[SIZE], y[SIZE]; + int i; + + fcoeffs = ff_iir_filter_init_coeffs(NULL, FF_FILTER_TYPE_BUTTERWORTH, + FF_FILTER_MODE_LOWPASS, FILT_ORDER, + cutoff_coeff, 0.0, 0.0); + fstate = ff_iir_filter_init_state(FILT_ORDER); + + for (i = 0; i < SIZE; i++) + x[i] = lrint(0.75 * INT16_MAX * sin(0.5 * M_PI * i * i / SIZE)); + + ff_iir_filter(fcoeffs, fstate, SIZE, x, 1, y, 1); + + for (i = 0; i < SIZE; i++) + printf("%6d %6d\n", x[i], y[i]); + + ff_iir_filter_free_coeffsp(&fcoeffs); + ff_iir_filter_free_statep(&fstate); + return 0; +} diff --git a/libavcodec/tests/imgconvert.c b/libavcodec/tests/imgconvert.c new file mode 100644 index 0000000000..c598d461d3 --- /dev/null +++ b/libavcodec/tests/imgconvert.c @@ -0,0 +1,50 @@ +/* + * Misc image conversion routines + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/imgconvert.c" + +#if FF_API_AVPICTURE +FF_DISABLE_DEPRECATION_WARNINGS +int main(void){ + int i; + int err=0; + int skip = 0; + + for (i=0; i<AV_PIX_FMT_NB*2; i++) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i); + if(!desc || !desc->name) { + skip ++; + continue; + } + if (skip) { + av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip); + skip = 0; + } + av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc)); + if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) { + av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n"); + err = 1; + } + } + return err; +} +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* FF_API_AVPICTURE */ diff --git a/libavcodec/tests/jpeg2000dwt.c b/libavcodec/tests/jpeg2000dwt.c new file mode 100644 index 0000000000..80b33bee79 --- /dev/null +++ b/libavcodec/tests/jpeg2000dwt.c @@ -0,0 +1,141 @@ +/* + * Discrete wavelet transform + * Copyright (c) 2007 Kamil Nowosad + * Copyright (c) 2013 Nicolas Bertrand <nicoinattendu@gmail.com> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/jpeg2000dwt.c" + +#include "libavutil/lfg.h" + +#define MAX_W 256 + +static int test_dwt(int *array, int *ref, int border[2][2], int decomp_levels, int type, int max_diff) { + int ret, j; + DWTContext s1={{{0}}}, *s= &s1; + int64_t err2 = 0; + + ret = ff_jpeg2000_dwt_init(s, border, decomp_levels, type); + if (ret < 0) { + fprintf(stderr, "ff_jpeg2000_dwt_init failed\n"); + return 1; + } + ret = ff_dwt_encode(s, array); + if (ret < 0) { + fprintf(stderr, "ff_dwt_encode failed\n"); + return 1; + } + ret = ff_dwt_decode(s, array); + if (ret < 0) { + fprintf(stderr, "ff_dwt_encode failed\n"); + return 1; + } + for (j = 0; j<MAX_W * MAX_W; j++) { + if (FFABS(array[j] - ref[j]) > max_diff) { + fprintf(stderr, "missmatch at %d (%d != %d) decomp:%d border %d %d %d %d\n", + j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]); + return 2; + } + err2 += (array[j] - ref[j]) * (array[j] - ref[j]); + array[j] = ref[j]; + } + ff_dwt_destroy(s); + + printf("%s, decomp:%2d border %3d %3d %3d %3d milli-err2:%9"PRId64"\n", + type == FF_DWT53 ? "5/3i" : "9/7i", + decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1], + 1000*err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0]))); + + return 0; +} + +static int test_dwtf(float *array, float *ref, int border[2][2], int decomp_levels, float max_diff) { + int ret, j; + DWTContext s1={{{0}}}, *s= &s1; + double err2 = 0; + + ret = ff_jpeg2000_dwt_init(s, border, decomp_levels, FF_DWT97); + if (ret < 0) { + fprintf(stderr, "ff_jpeg2000_dwt_init failed\n"); + return 1; + } + ret = ff_dwt_encode(s, array); + if (ret < 0) { + fprintf(stderr, "ff_dwt_encode failed\n"); + return 1; + } + ret = ff_dwt_decode(s, array); + if (ret < 0) { + fprintf(stderr, "ff_dwt_encode failed\n"); + return 1; + } + for (j = 0; j<MAX_W * MAX_W; j++) { + if (FFABS(array[j] - ref[j]) > max_diff) { + fprintf(stderr, "missmatch at %d (%f != %f) decomp:%d border %d %d %d %d\n", + j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]); + return 2; + } + err2 += (array[j] - ref[j]) * (array[j] - ref[j]); + array[j] = ref[j]; + } + ff_dwt_destroy(s); + + printf("9/7f, decomp:%2d border %3d %3d %3d %3d err2:%20.3f\n", + decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1], + err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0]))); + + return 0; +} + +static int array[MAX_W * MAX_W]; +static int ref [MAX_W * MAX_W]; +static float arrayf[MAX_W * MAX_W]; +static float reff [MAX_W * MAX_W]; + +int main(void) { + AVLFG prng; + int i,j; + int border[2][2]; + int ret, decomp_levels; + + av_lfg_init(&prng, 1); + + for (i = 0; i<MAX_W * MAX_W; i++) + arrayf[i] = reff[i] = array[i] = ref[i] = av_lfg_get(&prng) % 2048; + + for (i = 0; i < 100; i++) { + for (j=0; j<4; j++) + border[j>>1][j&1] = av_lfg_get(&prng) % MAX_W; + if (border[0][0] >= border[0][1] || border[1][0] >= border[1][1]) + continue; + decomp_levels = av_lfg_get(&prng) % FF_DWT_MAX_DECLVLS; + + ret = test_dwt(array, ref, border, decomp_levels, FF_DWT53, 0); + if (ret) + return ret; + ret = test_dwt(array, ref, border, decomp_levels, FF_DWT97_INT, FFMIN(7+5*decomp_levels, 15+3*decomp_levels)); + if (ret) + return ret; + ret = test_dwtf(arrayf, reff, border, decomp_levels, 0.05); + if (ret) + return ret; + } + + return 0; +} diff --git a/libavcodec/tests/mathops.c b/libavcodec/tests/mathops.c new file mode 100644 index 0000000000..33a059cad8 --- /dev/null +++ b/libavcodec/tests/mathops.c @@ -0,0 +1,41 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/mathops.h" + +#include <stdlib.h> + +int main(void) +{ + unsigned u; + + for(u=0; u<65536; u++) { + unsigned s = u*u; + unsigned root = ff_sqrt(s); + unsigned root_m1 = ff_sqrt(s-1); + if (s && root != u) { + fprintf(stderr, "ff_sqrt failed at %u with %u\n", s, root); + return 1; + } + if (u && root_m1 != u - 1) { + fprintf(stderr, "ff_sqrt failed at %u with %u\n", s, root); + return 1; + } + } + return 0; +} diff --git a/libavcodec/tests/motion.c b/libavcodec/tests/motion.c new file mode 100644 index 0000000000..d89f9408c2 --- /dev/null +++ b/libavcodec/tests/motion.c @@ -0,0 +1,152 @@ +/* + * (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * motion test. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "config.h" +#include "libavcodec/me_cmp.h" +#include "libavutil/internal.h" +#include "libavutil/lfg.h" +#include "libavutil/mem.h" +#include "libavutil/time.h" + +#undef printf + +#define WIDTH 64 +#define HEIGHT 64 + +static uint8_t img1[WIDTH * HEIGHT]; +static uint8_t img2[WIDTH * HEIGHT]; + +static void fill_random(uint8_t *tab, int size) +{ + int i; + AVLFG prng; + + av_lfg_init(&prng, 1); + for(i=0;i<size;i++) { + tab[i] = av_lfg_get(&prng) % 256; + } +} + +static void help(void) +{ + printf("motion-test [-h]\n" + "test motion implementations\n"); +} + +#define NB_ITS 500 + +int dummy; + +static void test_motion(const char *name, + me_cmp_func test_func, me_cmp_func ref_func) +{ + int x, y, d1, d2, it; + uint8_t *ptr; + int64_t ti; + printf("testing '%s'\n", name); + + /* test correctness */ + for(it=0;it<20;it++) { + + fill_random(img1, WIDTH * HEIGHT); + fill_random(img2, WIDTH * HEIGHT); + + for(y=0;y<HEIGHT-17;y++) { + for(x=0;x<WIDTH-17;x++) { + ptr = img2 + y * WIDTH + x; + d1 = test_func(NULL, img1, ptr, WIDTH, 8); + d2 = ref_func(NULL, img1, ptr, WIDTH, 8); + if (d1 != d2) { + printf("error: mmx=%d c=%d\n", d1, d2); + } + } + } + } + emms_c(); + + /* speed test */ + ti = av_gettime_relative(); + d1 = 0; + for(it=0;it<NB_ITS;it++) { + for(y=0;y<HEIGHT-17;y++) { + for(x=0;x<WIDTH-17;x++) { + ptr = img2 + y * WIDTH + x; + d1 += test_func(NULL, img1, ptr, WIDTH, 8); + } + } + } + emms_c(); + dummy = d1; /* avoid optimization */ + ti = av_gettime_relative() - ti; + + printf(" %0.0f kop/s\n", + (double)NB_ITS * (WIDTH - 16) * (HEIGHT - 16) / + (double)(ti / 1000.0)); +} + + +int main(int argc, char **argv) +{ + AVCodecContext *ctx; + int c; + MECmpContext cctx, mmxctx; + int flags[2] = { AV_CPU_FLAG_MMX, AV_CPU_FLAG_MMXEXT }; + int flags_size = HAVE_MMXEXT ? 2 : 1; + + if (argc > 1) { + help(); + return 1; + } + + printf("ffmpeg motion test\n"); + + ctx = avcodec_alloc_context3(NULL); + ctx->flags |= AV_CODEC_FLAG_BITEXACT; + av_force_cpu_flags(0); + memset(&cctx, 0, sizeof(cctx)); + ff_me_cmp_init(&cctx, ctx); + for (c = 0; c < flags_size; c++) { + int x; + av_force_cpu_flags(flags[c]); + memset(&mmxctx, 0, sizeof(mmxctx)); + ff_me_cmp_init(&mmxctx, ctx); + + for (x = 0; x < 2; x++) { + printf("%s for %dx%d pixels\n", c ? "mmx2" : "mmx", + x ? 8 : 16, x ? 8 : 16); + test_motion("mmx", mmxctx.pix_abs[x][0], cctx.pix_abs[x][0]); + test_motion("mmx_x2", mmxctx.pix_abs[x][1], cctx.pix_abs[x][1]); + test_motion("mmx_y2", mmxctx.pix_abs[x][2], cctx.pix_abs[x][2]); + test_motion("mmx_xy2", mmxctx.pix_abs[x][3], cctx.pix_abs[x][3]); + } + } + av_free(ctx); + + return 0; +} diff --git a/libavcodec/tests/options.c b/libavcodec/tests/options.c new file mode 100644 index 0000000000..7f0ee1d807 --- /dev/null +++ b/libavcodec/tests/options.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/options.c" + +static int dummy_init(AVCodecContext *ctx) +{ + //TODO: this code should set every possible pointer that could be set by codec and is not an option; + ctx->extradata_size = 8; + ctx->extradata = av_malloc(ctx->extradata_size); + return 0; +} + +static int dummy_close(AVCodecContext *ctx) +{ + av_freep(&ctx->extradata); + ctx->extradata_size = 0; + return 0; +} + +static int dummy_encode(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) +{ + return AVERROR(ENOSYS); +} + +typedef struct Dummy12Context { + AVClass *av_class; + int num; + char* str; +} Dummy12Context; + +typedef struct Dummy3Context { + void *fake_av_class; + int num; + char* str; +} Dummy3Context; + +#define OFFSET(x) offsetof(Dummy12Context, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption dummy_options[] = { + { "str", "set str", OFFSET(str), AV_OPT_TYPE_STRING, { .str = "i'm src default value" }, 0, 0, VE}, + { "num", "set num", OFFSET(num), AV_OPT_TYPE_INT, { .i64 = 1500100900 }, 0, INT_MAX, VE}, + { NULL }, +}; + +static const AVClass dummy_v1_class = { + .class_name = "dummy_v1_class", + .item_name = av_default_item_name, + .option = dummy_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVClass dummy_v2_class = { + .class_name = "dummy_v2_class", + .item_name = av_default_item_name, + .option = dummy_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +/* codec with options */ +static AVCodec dummy_v1_encoder = { + .name = "dummy_v1_codec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_NONE - 1, + .encode2 = dummy_encode, + .init = dummy_init, + .close = dummy_close, + .priv_class = &dummy_v1_class, + .priv_data_size = sizeof(Dummy12Context), +}; + +/* codec with options, different class */ +static AVCodec dummy_v2_encoder = { + .name = "dummy_v2_codec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_NONE - 2, + .encode2 = dummy_encode, + .init = dummy_init, + .close = dummy_close, + .priv_class = &dummy_v2_class, + .priv_data_size = sizeof(Dummy12Context), +}; + +/* codec with priv data, but no class */ +static AVCodec dummy_v3_encoder = { + .name = "dummy_v3_codec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_NONE - 3, + .encode2 = dummy_encode, + .init = dummy_init, + .close = dummy_close, + .priv_data_size = sizeof(Dummy3Context), +}; + +/* codec without priv data */ +static AVCodec dummy_v4_encoder = { + .name = "dummy_v4_codec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_NONE - 4, + .encode2 = dummy_encode, + .init = dummy_init, + .close = dummy_close, +}; + +static void test_copy_print_codec(const AVCodecContext *ctx) +{ + printf("%-14s: %dx%d prv: %s", + ctx->codec ? ctx->codec->name : "NULL", + ctx->width, ctx->height, + ctx->priv_data ? "set" : "null"); + if (ctx->codec && ctx->codec->priv_class && ctx->codec->priv_data_size) { + int64_t i64; + char *str = NULL; + av_opt_get_int(ctx->priv_data, "num", 0, &i64); + av_opt_get(ctx->priv_data, "str", 0, (uint8_t**)&str); + printf(" opts: %"PRId64" %s", i64, str); + av_free(str); + } + printf("\n"); +} + +static void test_copy(const AVCodec *c1, const AVCodec *c2) +{ + AVCodecContext *ctx1, *ctx2; + printf("%s -> %s\nclosed:\n", c1 ? c1->name : "NULL", c2 ? c2->name : "NULL"); + ctx1 = avcodec_alloc_context3(c1); + ctx2 = avcodec_alloc_context3(c2); + ctx1->width = ctx1->height = 128; + if (ctx2->codec && ctx2->codec->priv_class && ctx2->codec->priv_data_size) { + av_opt_set(ctx2->priv_data, "num", "667", 0); + av_opt_set(ctx2->priv_data, "str", "i'm dest value before copy", 0); + } + avcodec_copy_context(ctx2, ctx1); + test_copy_print_codec(ctx1); + test_copy_print_codec(ctx2); + if (ctx1->codec) { + int ret; + printf("opened:\n"); + ret = avcodec_open2(ctx1, ctx1->codec, NULL); + if (ret < 0) { + fprintf(stderr, "avcodec_open2 failed\n"); + exit(1); + } + if (ctx2->codec && ctx2->codec->priv_class && ctx2->codec->priv_data_size) { + av_opt_set(ctx2->priv_data, "num", "667", 0); + av_opt_set(ctx2->priv_data, "str", "i'm dest value before copy", 0); + } + avcodec_copy_context(ctx2, ctx1); + test_copy_print_codec(ctx1); + test_copy_print_codec(ctx2); + avcodec_close(ctx1); + } + avcodec_free_context(&ctx1); + avcodec_free_context(&ctx2); +} + +int main(void) +{ + AVCodec *dummy_codec[] = { + &dummy_v1_encoder, + &dummy_v2_encoder, + &dummy_v3_encoder, + &dummy_v4_encoder, + NULL, + }; + int i, j; + + for (i = 0; dummy_codec[i]; i++) + avcodec_register(dummy_codec[i]); + + printf("testing avcodec_copy_context()\n"); + for (i = 0; i < FF_ARRAY_ELEMS(dummy_codec); i++) + for (j = 0; j < FF_ARRAY_ELEMS(dummy_codec); j++) + test_copy(dummy_codec[i], dummy_codec[j]); + return 0; +} diff --git a/libavcodec/tests/ppc/dct.c b/libavcodec/tests/ppc/dct.c new file mode 100644 index 0000000000..d95db525af --- /dev/null +++ b/libavcodec/tests/ppc/dct.c @@ -0,0 +1,32 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavcodec/ppc/fdct.h" + +static const struct algo fdct_tab_arch[] = { +#if HAVE_ALTIVEC + { "altivecfdct", ff_fdct_altivec, FF_IDCT_PERM_NONE, AV_CPU_FLAG_ALTIVEC }, +#endif + { 0 } +}; + +static const struct algo idct_tab_arch[] = { + { 0 } +}; diff --git a/libavcodec/tests/rangecoder.c b/libavcodec/tests/rangecoder.c new file mode 100644 index 0000000000..2da5c0ce33 --- /dev/null +++ b/libavcodec/tests/rangecoder.c @@ -0,0 +1,64 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdint.h> +#include <string.h> + +#include "libavutil/lfg.h" +#include "libavutil/log.h" + +#include "libavcodec/rangecoder.h" + +#define SIZE 10240 + +int main(void) +{ + RangeCoder c; + uint8_t b[9 * SIZE]; + uint8_t r[9 * SIZE]; + int i; + uint8_t state[10]; + AVLFG prng; + + av_lfg_init(&prng, 1); + + ff_init_range_encoder(&c, b, SIZE); + ff_build_rac_states(&c, (1LL << 32) / 20, 128 + 64 + 32 + 16); + + memset(state, 128, sizeof(state)); + + for (i = 0; i < SIZE; i++) + r[i] = av_lfg_get(&prng) % 7; + + for (i = 0; i < SIZE; i++) + put_rac(&c, state, r[i] & 1); + + ff_rac_terminate(&c); + + ff_init_range_decoder(&c, b, SIZE); + + memset(state, 128, sizeof(state)); + + for (i = 0; i < SIZE; i++) + if ((r[i] & 1) != get_rac(&c, state)) { + av_log(NULL, AV_LOG_ERROR, "rac failure at %d\n", i); + return 1; + } + + return 0; +} diff --git a/libavcodec/tests/snowenc.c b/libavcodec/tests/snowenc.c new file mode 100644 index 0000000000..d5f94e8a61 --- /dev/null +++ b/libavcodec/tests/snowenc.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/snowenc.c" + +#undef malloc +#undef free +#undef printf + +#include "libavutil/lfg.h" +#include "libavutil/mathematics.h" + +int main(void){ +#define width 256 +#define height 256 + int buffer[2][width*height]; + SnowContext s; + int i; + AVLFG prng; + s.spatial_decomposition_count=6; + s.spatial_decomposition_type=1; + + s.temp_dwt_buffer = av_mallocz_array(width, sizeof(DWTELEM)); + s.temp_idwt_buffer = av_mallocz_array(width, sizeof(IDWTELEM)); + + if (!s.temp_dwt_buffer || !s.temp_idwt_buffer) { + fprintf(stderr, "Failed to allocate memory\n"); + return 1; + } + + av_lfg_init(&prng, 1); + + printf("testing 5/3 DWT\n"); + for(i=0; i<width*height; i++) + buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345; + + ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + + for(i=0; i<width*height; i++) + if(buffer[0][i]!= buffer[1][i]) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]); + + printf("testing 9/7 DWT\n"); + s.spatial_decomposition_type=0; + for(i=0; i<width*height; i++) + buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345; + + ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + + for(i=0; i<width*height; i++) + if(FFABS(buffer[0][i] - buffer[1][i])>20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]); + + { + int level, orientation, x, y; + int64_t errors[8][4]; + int64_t g=0; + + memset(errors, 0, sizeof(errors)); + s.spatial_decomposition_count=3; + s.spatial_decomposition_type=0; + for(level=0; level<s.spatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + int w= width >> (s.spatial_decomposition_count-level); + int h= height >> (s.spatial_decomposition_count-level); + int stride= width << (s.spatial_decomposition_count-level); + DWTELEM *buf= buffer[0]; + int64_t error=0; + + if(orientation&1) buf+=w; + if(orientation>1) buf+=stride>>1; + + memset(buffer[0], 0, sizeof(int)*width*height); + buf[w/2 + h/2*stride]= 256*256; + ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + for(y=0; y<height; y++){ + for(x=0; x<width; x++){ + int64_t d= buffer[0][x + y*width]; + error += d*d; + if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9 && level==2) printf("%8"PRId64" ", d); + } + if(FFABS(height/2-y)<9 && level==2) printf("\n"); + } + error= (int)(sqrt(error)+0.5); + errors[level][orientation]= error; + if(g) g=av_gcd(g, error); + else g= error; + } + } + printf("static int const visual_weight[][4]={\n"); + for(level=0; level<s.spatial_decomposition_count; level++){ + printf(" {"); + for(orientation=0; orientation<4; orientation++){ + printf("%8"PRId64",", errors[level][orientation]/g); + } + printf("},\n"); + } + printf("};\n"); + { + int level=2; + int w= width >> (s.spatial_decomposition_count-level); + //int h= height >> (s.spatial_decomposition_count-level); + int stride= width << (s.spatial_decomposition_count-level); + DWTELEM *buf= buffer[0]; + int64_t error=0; + + buf+=w; + buf+=stride>>1; + + memset(buffer[0], 0, sizeof(int)*width*height); + for(y=0; y<height; y++){ + for(x=0; x<width; x++){ + int tab[4]={0,2,3,1}; + buffer[0][x+width*y]= 256*256*tab[(x&1) + 2*(y&1)]; + } + } + ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + for(y=0; y<height; y++){ + for(x=0; x<width; x++){ + int64_t d= buffer[0][x + y*width]; + error += d*d; + if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9) printf("%8"PRId64" ", d); + } + if(FFABS(height/2-y)<9) printf("\n"); + } + } + + } + return 0; +} diff --git a/libavcodec/tests/utils.c b/libavcodec/tests/utils.c new file mode 100644 index 0000000000..e2891fb389 --- /dev/null +++ b/libavcodec/tests/utils.c @@ -0,0 +1,37 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/avcodec.h" + +int main(void){ + AVCodec *codec = NULL; + int ret = 0; + avcodec_register_all(); + + while (codec = av_codec_next(codec)) { + if (av_codec_is_encoder(codec)) { + if (codec->type == AVMEDIA_TYPE_AUDIO) { + if (!codec->sample_fmts) { + av_log(NULL, AV_LOG_FATAL, "Encoder %s is missing the sample_fmts field\n", codec->name); + ret = 1; + } + } + } + } + return ret; +} diff --git a/libavcodec/tests/x86/dct.c b/libavcodec/tests/x86/dct.c new file mode 100644 index 0000000000..b6cdfb346c --- /dev/null +++ b/libavcodec/tests/x86/dct.c @@ -0,0 +1,133 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavcodec/x86/fdct.h" +#include "libavcodec/x86/xvididct.h" +#include "libavcodec/x86/simple_idct.h" + +#if (CONFIG_PRORES_DECODER || CONFIG_PRORES_LGPL_DECODER) && ARCH_X86_64 && HAVE_YASM +void ff_prores_idct_put_10_sse2(uint16_t *dst, int linesize, + int16_t *block, int16_t *qmat); + +#define PR_WRAP(INSN) \ +static void ff_prores_idct_put_10_##INSN##_wrap(int16_t *dst){ \ + LOCAL_ALIGNED(16, int16_t, qmat, [64]); \ + LOCAL_ALIGNED(16, int16_t, tmp, [64]); \ + int i; \ + \ + for(i=0; i<64; i++){ \ + qmat[i]=4; \ + tmp[i]= dst[i]; \ + } \ + ff_prores_idct_put_10_##INSN (dst, 16, tmp, qmat); \ + \ + for(i=0; i<64; i++) { \ + dst[i] -= 512; \ + } \ +} + +PR_WRAP(sse2) + +# if HAVE_AVX_EXTERNAL +void ff_prores_idct_put_10_avx(uint16_t *dst, int linesize, + int16_t *block, int16_t *qmat); +PR_WRAP(avx) +# endif + +#endif + +static const struct algo fdct_tab_arch[] = { +#if HAVE_MMX_INLINE + { "MMX", ff_fdct_mmx, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMX }, +#endif +#if HAVE_MMXEXT_INLINE + { "MMXEXT", ff_fdct_mmxext, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMXEXT }, +#endif +#if HAVE_SSE2_INLINE + { "SSE2", ff_fdct_sse2, FF_IDCT_PERM_NONE, AV_CPU_FLAG_SSE2 }, +#endif + { 0 } +}; + +static const struct algo idct_tab_arch[] = { +#if HAVE_MMX_INLINE + { "SIMPLE-MMX", ff_simple_idct_mmx, FF_IDCT_PERM_SIMPLE, AV_CPU_FLAG_MMX }, +#endif +#if CONFIG_MPEG4_DECODER && HAVE_YASM +#if ARCH_X86_32 + { "XVID-MMX", ff_xvid_idct_mmx, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMX, 1 }, + { "XVID-MMXEXT", ff_xvid_idct_mmxext, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMXEXT, 1 }, +#endif +#if HAVE_SSE2_EXTERNAL + { "XVID-SSE2", ff_xvid_idct_sse2, FF_IDCT_PERM_SSE2, AV_CPU_FLAG_SSE2, 1 }, +#endif +#endif /* CONFIG_MPEG4_DECODER && HAVE_YASM */ +#if (CONFIG_PRORES_DECODER || CONFIG_PRORES_LGPL_DECODER) && ARCH_X86_64 && HAVE_YASM + { "PR-SSE2", ff_prores_idct_put_10_sse2_wrap, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2, 1 }, +# if HAVE_AVX_EXTERNAL + { "PR-AVX", ff_prores_idct_put_10_avx_wrap, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_AVX, 1 }, +# endif +#endif +#if HAVE_YASM +#if ARCH_X86_64 +#if HAVE_SSE2_EXTERNAL + { "SIMPLE10-SSE2", ff_simple_idct10_sse2, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2}, + { "SIMPLE12-SSE2", ff_simple_idct12_sse2, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2, 1 }, +#endif +#if HAVE_AVX_EXTERNAL + { "SIMPLE10-AVX", ff_simple_idct10_avx, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_AVX}, + { "SIMPLE12-AVX", ff_simple_idct12_avx, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_AVX, 1 }, +#endif +#endif +#endif + { 0 } +}; + +static const uint8_t idct_simple_mmx_perm[64] = { + 0x00, 0x08, 0x04, 0x09, 0x01, 0x0C, 0x05, 0x0D, + 0x10, 0x18, 0x14, 0x19, 0x11, 0x1C, 0x15, 0x1D, + 0x20, 0x28, 0x24, 0x29, 0x21, 0x2C, 0x25, 0x2D, + 0x12, 0x1A, 0x16, 0x1B, 0x13, 0x1E, 0x17, 0x1F, + 0x02, 0x0A, 0x06, 0x0B, 0x03, 0x0E, 0x07, 0x0F, + 0x30, 0x38, 0x34, 0x39, 0x31, 0x3C, 0x35, 0x3D, + 0x22, 0x2A, 0x26, 0x2B, 0x23, 0x2E, 0x27, 0x2F, + 0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F, +}; + +static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 }; + +static int permute_x86(int16_t dst[64], const int16_t src[64], + enum idct_permutation_type perm_type) +{ + int i; + + switch (perm_type) { + case FF_IDCT_PERM_SIMPLE: + for (i = 0; i < 64; i++) + dst[idct_simple_mmx_perm[i]] = src[i]; + return 1; + case FF_IDCT_PERM_SSE2: + for (i = 0; i < 64; i++) + dst[(i & 0x38) | idct_sse2_row_perm[i & 7]] = src[i]; + return 1; + } + + return 0; +} |