[FFmpeg-devel] [PATCH] 1D DCT for dsputil
Daniel Verkamp
daniel
Mon Dec 21 20:02:00 CET 2009
Hi,
In an effort to get at least some parts of the Bink patch committed, I
am splitting it into separable pieces.
This is a one-dimensional floating-point DCT used by Bink audio. The
actual code was written by Peter Ross.
The comments I myself have about this code:
- Should it be using math.h cos()/sin() or some lookup table approach?
- Can there be a test written? (I don't know enough about the math
involved to write a sane test...)
Thanks,
-- Daniel Verkamp
-------------- next part --------------
>From 8444704a0d1903aa641a7e4d6afd6d06ddf8e67c Mon Sep 17 00:00:00 2001
From: Daniel Verkamp <daniel at drv.nu>
Date: Mon, 21 Dec 2009 13:40:08 -0500
Subject: [PATCH] Add DCT to dsputil
Written by Peter Ross (pross xvid org)
---
configure | 2 +
libavcodec/Makefile | 1 +
libavcodec/dct.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++
libavcodec/dsputil.h | 18 +++++++++
4 files changed, 116 insertions(+), 0 deletions(-)
create mode 100644 libavcodec/dct.c
diff --git a/configure b/configure
index 7b85fa8..623c10a 100755
--- a/configure
+++ b/configure
@@ -99,6 +99,7 @@ Configuration options:
--disable-fastdiv disable table-based division
--enable-small optimize for size instead of speed
--disable-aandct disable AAN DCT code
+ --disable-dct disable DCT code
--disable-fft disable FFT code
--disable-golomb disable Golomb code
--disable-lpc disable LPC code
@@ -826,6 +827,7 @@ CONFIG_LIST="
avisynth
beos_netserver
bzlib
+ dct
doc
fastdiv
ffmpeg
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index f865d53..d00502d 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -27,6 +27,7 @@ OBJS = allcodecs.o \
# parts needed for many different codecs
OBJS-$(CONFIG_AANDCT) += aandcttab.o
OBJS-$(CONFIG_ENCODERS) += faandct.o jfdctfst.o jfdctint.o
+OBJS-$(CONFIG_DCT) += dct.o
FFT-OBJS-$(CONFIG_HARDCODED_TABLES) += cos_tables.o
OBJS-$(CONFIG_FFT) += fft.o $(FFT-OBJS-yes)
OBJS-$(CONFIG_GOLOMB) += golomb.o
diff --git a/libavcodec/dct.c b/libavcodec/dct.c
new file mode 100644
index 0000000..806b4ea
--- /dev/null
+++ b/libavcodec/dct.c
@@ -0,0 +1,95 @@
+/*
+ * (I)DCT Transforms
+ * Copyright (c) 2009 Peter Ross (pross at xvid.org)
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file libavcodec/dct.c
+ * (Inverse) Discrete Cosine Transforms
+ */
+
+#include <math.h>
+#include "dsputil.h"
+
+av_cold int ff_dct_init(DCTContext *s, int nbits, int inverse)
+{
+ int n = 1 << nbits;
+
+ s->nbits = nbits;
+ s->inverse = inverse;
+
+ s->data = av_malloc(sizeof(FFTComplex) * 2 * n);
+ if (!s->data)
+ return -1;
+
+ if (ff_fft_init(&s->fft, nbits+1, inverse) < 0)
+ return -1;
+
+ return 0;
+}
+
+static void ff_dct_calc_c(DCTContext *s, FFTSample *data)
+{
+ int n = 1<<s->nbits;
+ int i;
+
+#define ROTATE(i,n) (-M_PI*((n)-0.5f)*(i)/(n))
+ if (s->inverse) {
+ for(i=0; i < n; i++) {
+ s->data[i].re = 2 * data[i] * cos(ROTATE(i,n));
+ s->data[i].im = 2 * data[i] * sin(ROTATE(i,n));
+ }
+ s->data[n].re = 0;
+ s->data[n].im = 0;
+ for(i=0; i<n-1; i++) {
+ s->data[n+i+1].re = -2 * data[n - (i+1)] * cos(ROTATE(n+i+1,n));
+ s->data[n+i+1].im = -2 * data[n - (i+1)] * sin(ROTATE(n+i+1,n));
+ }
+ }else{
+ for(i=0; i < n; i++) {
+ s->data[i].re = data[n - (i+1)];
+ s->data[i].im = 0;
+ s->data[n+i].re = data[i];
+ s->data[n+i].im = 0;
+ }
+ }
+
+ ff_fft_permute(&s->fft, s->data);
+ ff_fft_calc(&s->fft, s->data);
+
+ if (s->inverse) {
+ for(i=0; i < n; i++)
+ data[i] = s->data[n-(i+1)].re / (2 * n);
+ }else {
+ for(i=0; i < n; i++)
+ data[i] = s->data[i].re / (2 * cos(ROTATE(i,n)));
+ }
+#undef ROTATE
+}
+
+void ff_dct_calc(DCTContext *s, FFTSample *data)
+{
+ ff_dct_calc_c(s, data);
+}
+
+av_cold void ff_dct_end(DCTContext *s)
+{
+ ff_fft_end(&s->fft);
+ av_free(s->data);
+}
diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h
index e483276..83359b5 100644
--- a/libavcodec/dsputil.h
+++ b/libavcodec/dsputil.h
@@ -891,6 +891,24 @@ int ff_rdft_init(RDFTContext *s, int nbits, enum RDFTransformType trans);
void ff_rdft_calc(RDFTContext *s, FFTSample *data);
void ff_rdft_end(RDFTContext *s);
+/* Discrete Cosine Transform */
+
+typedef struct {
+ int nbits;
+ int inverse;
+ FFTComplex *data;
+ FFTContext fft;
+} DCTContext;
+
+/**
+ * Sets up (Inverse)DCT.
+ * @param nbits log2 of the length of the input array
+ * @param inverse >0 forward transform, <0 inverse transform
+ */
+int ff_dct_init(DCTContext *s, int nbits, int inverse);
+void ff_dct_calc(DCTContext *s, FFTSample *data);
+void ff_dct_end(DCTContext *s);
+
#define WRAPPER8_16(name8, name16)\
static int name16(void /*MpegEncContext*/ *s, uint8_t *dst, uint8_t *src, int stride, int h){\
return name8(s, dst , src , stride, h)\
--
1.6.6.rc3
More information about the ffmpeg-devel
mailing list