[FFmpeg-soc] [soc]: r3880 - in dirac/libavcodec: diracdec.c dwt.c dwt.h
conrad
subversion at mplayerhq.hu
Tue Dec 9 23:05:47 CET 2008
Author: conrad
Date: Tue Dec 9 23:05:47 2008
New Revision: 3880
Log:
Rewrite idwt in the style of Snow's, making it mostly in-place and removing
the need for a temp buffer. 20% faster intra decode.
Added:
dirac/libavcodec/dwt.c
dirac/libavcodec/dwt.h
Modified:
dirac/libavcodec/diracdec.c
Modified: dirac/libavcodec/diracdec.c
==============================================================================
--- dirac/libavcodec/diracdec.c (original)
+++ dirac/libavcodec/diracdec.c Tue Dec 9 23:05:47 2008
@@ -34,6 +34,7 @@
#include "dirac_arith.h"
#include "dirac_wavelet.h"
#include "mpeg12data.h"
+#include "dwt.h"
/**
* Value of Picture.reference when Picture is not a reference picture, but
@@ -600,50 +601,15 @@ static int dirac_unpack_block_motion_dat
}
/**
- * IDWT
- *
- * @param coeffs coefficients to transform
- * @return returns 0 on succes, otherwise -1
- */
-int dirac_idwt(DiracContext *s, int16_t *coeffs, int16_t *synth, int comp)
-{
- int level;
- int width, height;
-
- for (level = 1; level <= s->decoding.wavelet_depth; level++) {
- width = s->plane[comp].band[level-1][1].width;
- height = s->plane[comp].band[level-1][1].height;
-
- switch(s->wavelet_idx) {
- case 0:
- dirac_subband_idwt_97(s->avctx, width, height, s->plane[comp].padded_width,
- coeffs, synth, level);
- break;
- case 1:
- dirac_subband_idwt_53(s->avctx, width, height, s->plane[comp].padded_width,
- coeffs, synth, level);
- break;
- default:
- av_log(s->avctx, AV_LOG_INFO, "unknown IDWT index: %d\n",
- s->wavelet_idx);
- }
- }
-
- return 0;
-}
-
-/**
* Decode a frame.
*
* @return 0 when successful, otherwise -1 is returned
*/
static int dirac_decode_frame_internal(DiracContext *s)
{
- AVCodecContext *avctx = s->avctx;
int16_t *coeffs;
int16_t *line;
int16_t *mcline;
- int16_t *synth;
int comp, level, orientation;
int x, y;
@@ -673,15 +639,15 @@ static int dirac_decode_frame_internal(D
b->ibuf = coeffs;
b->level = level;
- b->stride = s->plane[comp].padded_width;
+ b->stride = s->plane[comp].padded_width << (s->decoding.wavelet_depth - level);
b->width = (w + !(orientation&1))>>1;
b->height = (h + !(orientation>1))>>1;
b->orientation = orientation;
if (orientation & 1)
- b->ibuf += b->width;
+ b->ibuf += (w+1)>>1;
if (orientation > 1)
- b->ibuf += b->height * b->stride;
+ b->ibuf += b->stride>>1;
if (level)
b->parent = &s->plane[comp].band[level-1][orientation];
@@ -691,13 +657,6 @@ static int dirac_decode_frame_internal(D
}
}
- /* Allocate memory for the IDWT to work in. */
- synth = av_malloc(s->plane[0].padded_width * s->plane[0].padded_height * sizeof(int16_t));
- if (!synth) {
- av_log(avctx, AV_LOG_ERROR, "av_malloc() failed\n");
- return -1;
- }
-
for (comp = 0; comp < 3; comp++) {
uint8_t *frame = s->current_picture->data[comp];
int width, height;
@@ -711,7 +670,8 @@ static int dirac_decode_frame_internal(D
if (!s->zero_res)
decode_component(s, comp);
- dirac_idwt(s, coeffs, synth, comp);
+ ff_spatial_idwt2(coeffs, s->plane[comp].padded_width, s->plane[comp].padded_height,
+ s->plane[comp].padded_width, s->wavelet_idx+2, s->decoding.wavelet_depth);
if (s->refs) {
if (dirac_motion_compensation(s, coeffs, comp)) {
@@ -758,7 +718,6 @@ static int dirac_decode_frame_internal(D
av_freep(&s->blmotion);
}
av_free(coeffs);
- av_free(synth);
return 0;
}
Added: dirac/libavcodec/dwt.c
==============================================================================
--- (empty file)
+++ dirac/libavcodec/dwt.c Tue Dec 9 23:05:47 2008
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2004 Michael Niedermayer <michaelni at gmx.at>
+ * Copyright (C) 2008 David Conrad
+ *
+ * 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 "avcodec.h"
+#include "dsputil.h"
+#include "dwt.h"
+
+static inline int mirror(int v, int m){
+ if (v<0) return -v;
+ else if(v>m) return 2*m-v;
+ else return v;
+}
+
+static inline int extend(int v, int m){
+ if (v<0) return 0;
+ else if(v>m) return m;
+ else return v;
+}
+
+#define COMPOSE_53iL0(b0, b1, b2)\
+ (b1 - ((b0 + b2 + 2) >> 2))
+
+#define COMPOSE_DIRAC53iH0(b0, b1, b2)\
+ (b1 + ((b0 + b2 + 1) >> 1))
+
+#define COMPOSE_DD97iH0(b0, b1, b2, b3, b4)\
+ (b2 + ((-b0 + 9*b1 + 9*b3 - b4 + 8) >> 4))
+
+static av_always_inline
+void interleave(IDWTELEM *dst, IDWTELEM *src0, IDWTELEM *src1, int width,
+ int add, int shift){
+ int i;
+ for (i = 0; i < width>>1; i++) {
+ dst[2*i ] = (src0[i] + add) >> shift;
+ dst[2*i+1] = (src1[i] + add) >> shift;
+ }
+}
+
+static void horizontal_compose_dirac53i(IDWTELEM *b, int w){
+ IDWTELEM temp[w];
+ const int w2= w >> 1;
+ int x;
+
+ temp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
+ for (x = 0; x < w2-1; x++) {
+ temp[x+1 ] = COMPOSE_53iL0 (b[x+w2], b[x+1 ], b[x+w2+1]);
+ temp[x+w2] = COMPOSE_DIRAC53iH0(temp[x], b[x+w2], temp[x+1]);
+ }
+ temp[w-1] = COMPOSE_DIRAC53iH0(temp[w2-1], b[w-1], temp[w2-1]);
+
+ interleave(b, temp, temp+w2, w, 1, 1);
+}
+
+static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
+ int width){
+ int i;
+
+ for(i=0; i<width; i++){
+ b1[i] = COMPOSE_53iL0(b0[i], b1[i], b2[i]);
+ }
+}
+
+static void vertical_compose_dirac53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
+ int width){
+ int i;
+
+ for(i=0; i<width; i++){
+ b1[i] = COMPOSE_DIRAC53iH0(b0[i], b1[i], b2[i]);
+ }
+}
+
+static void spatial_compose_dirac53i_dy(dwt_compose_t *cs, IDWTELEM *buffer,
+ int width, int height, int stride){
+ int y= cs->y;
+ IDWTELEM *b0= cs->b0;
+ IDWTELEM *b1= cs->b1;
+ IDWTELEM *b2= buffer + mirror(y+1, height-1)*stride;
+ IDWTELEM *b3= buffer + mirror(y+2, height-1)*stride;
+
+ if(y+1<(unsigned)height) vertical_compose53iL0 (b1, b2, b3, width);
+ if(y+0<(unsigned)height) vertical_compose_dirac53iH0(b0, b1, b2, width);
+
+ if(y-1<(unsigned)height) horizontal_compose_dirac53i(b0, width);
+ if(y+0<(unsigned)height) horizontal_compose_dirac53i(b1, width);
+
+ cs->b0 = b2;
+ cs->b1 = b3;
+ cs->y += 2;
+}
+
+static void horizontal_compose_dd97i(IDWTELEM *b, int w){
+ IDWTELEM temp[w];
+ const int w2 = w >> 1;
+ int x;
+
+ temp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
+ for (x = 0; x < w2-1; x++)
+ temp[x+1] = COMPOSE_53iL0(b[x+w2], b[x+1], b[x+w2+1]);
+
+ temp[w2] = COMPOSE_DD97iH0(temp[0], temp[0], b[w2], temp[1], temp[2]);
+ for (x = 0; x < w2-2; x++)
+ temp[x+w2+1] = COMPOSE_DD97iH0(temp[x], temp[x+1], b[x+w2+1], temp[x+2], temp[x+3]);
+
+ temp[w-2] = COMPOSE_DD97iH0(temp[w2-3], temp[w2-2], b[w-2], temp[w2-1], temp[w2-1]);
+ temp[w-1] = COMPOSE_DD97iH0(temp[w2-2], temp[w2-1], b[w-1], temp[w2-1], temp[w2-1]);
+
+ interleave(b, temp, temp+w2, w, 1, 1);
+}
+
+static void vertical_compose_dd97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
+ IDWTELEM *b3, IDWTELEM *b4, int width){
+ int i;
+
+ for(i=0; i<width; i++){
+ b2[i] = COMPOSE_DD97iH0(b0[i], b1[i], b2[i], b3[i], b4[i]);
+ }
+}
+
+static void spatial_compose_dd97i_dy(dwt_compose_t *cs, IDWTELEM *buffer,
+ int width, int height, int stride){
+ int y = cs->y;
+ IDWTELEM *b0= cs->b0;
+ IDWTELEM *b1= cs->b1;
+ IDWTELEM *b2= cs->b2;
+ IDWTELEM *b3= cs->b3;
+ IDWTELEM *b4= cs->b4;
+ IDWTELEM *b5= cs->b5;
+ IDWTELEM *b6= buffer + extend(y+5, height-2)*stride;
+ IDWTELEM *b7= buffer + mirror(y+6, height-1)*stride;
+
+ if(y+5<(unsigned)height) vertical_compose53iL0 ( b5, b6, b7, width);
+ if(y+1<(unsigned)height) vertical_compose_dd97iH0(b0, b2, b3, b4, b6, width);
+
+ if(y-1<(unsigned)height) horizontal_compose_dd97i(b0, width);
+ if(y+0<(unsigned)height) horizontal_compose_dd97i(b1, width);
+
+ cs->b0=b2;
+ cs->b1=b3;
+ cs->b2=b4;
+ cs->b3=b5;
+ cs->b4=b6;
+ cs->b5=b7;
+ cs->y += 2;
+}
+
+static void spatial_compose53i_init(dwt_compose_t *cs, IDWTELEM *buffer,
+ int height, int stride){
+ cs->b0 = buffer + mirror(-1-1, height-1)*stride;
+ cs->b1 = buffer + mirror(-1 , height-1)*stride;
+ cs->y = -1;
+}
+
+static void spatial_compose_dd97i_init(dwt_compose_t *cs, IDWTELEM *buffer,
+ int height, int stride){
+ cs->b0 = buffer + extend(-5-1, height-2)*stride;
+ cs->b1 = buffer + mirror(-5 , height-1)*stride;
+ cs->b2 = buffer + extend(-5+1, height-2)*stride;
+ cs->b3 = buffer + mirror(-5+2, height-1)*stride;
+ cs->b4 = buffer + extend(-5+3, height-2)*stride;
+ cs->b5 = buffer + mirror(-5+4, height-1)*stride;
+ cs->y = -5;
+}
+
+void ff_spatial_idwt_init2(dwt_compose_t *cs, IDWTELEM *buffer, int width, int height,
+ int stride, int type, int decomposition_count){
+ int level;
+ for(level=decomposition_count-1; level>=0; level--){
+ int hl = height >> level;
+ int stride_l = stride << level;
+
+ switch(type){
+ case DWT_DIRAC_DD9_7:
+ spatial_compose_dd97i_init(cs+level, buffer, hl, stride_l);
+ break;
+ case DWT_DIRAC_LEGALL5_3:
+ spatial_compose53i_init(cs+level, buffer, hl, stride_l);
+ break;
+ }
+ }
+}
+
+void ff_spatial_idwt_slice2(dwt_compose_t *cs, IDWTELEM *buffer, int width, int height,
+ int stride, int type, int decomposition_count, int y){
+ const int support[] = {5, 3, 7, 3};
+ int level;
+
+ for(level=decomposition_count-1; level>=0; level--){
+ int wl = width >> level;
+ int hl = height >> level;
+ int stride_l = stride << level;
+
+ while(cs[level].y <= FFMIN((y>>level)+support[type], height>>level)){
+ switch(type){
+ case DWT_DIRAC_DD9_7:
+ spatial_compose_dd97i_dy(cs+level, buffer, wl, hl, stride_l);
+ break;
+ case DWT_DIRAC_LEGALL5_3:
+ spatial_compose_dirac53i_dy(cs+level, buffer, wl, hl, stride_l);
+ break;
+ }
+ }
+ }
+}
+
+void ff_spatial_idwt2(IDWTELEM *buffer, int width, int height,
+ int stride, int type, int decomposition_count){
+ dwt_compose_t cs[decomposition_count];
+ int y;
+
+ ff_spatial_idwt_init2(cs, buffer, width, height, stride,
+ type, decomposition_count);
+ for(y=0; y<height; y+=4)
+ ff_spatial_idwt_slice2(cs, buffer, width, height, stride,
+ type, decomposition_count, y);
+}
Added: dirac/libavcodec/dwt.h
==============================================================================
--- (empty file)
+++ dirac/libavcodec/dwt.h Tue Dec 9 23:05:47 2008
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004 Michael Niedermayer <michaelni at 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
+ */
+
+#ifndef AVCODEC_DWT_H
+#define AVCODEC_DWT_H
+
+#include "avcodec.h"
+#include "dsputil.h"
+
+typedef struct {
+ int y;
+ IDWTELEM *b0;
+ IDWTELEM *b1;
+ IDWTELEM *b2;
+ IDWTELEM *b3;
+ IDWTELEM *b4;
+ IDWTELEM *b5;
+} dwt_compose_t;
+
+#define DWT_SNOW_DAUB9_7 0
+#define DWT_SNOW_LEGALL5_3 1
+#define DWT_DIRAC_DD9_7 2
+#define DWT_DIRAC_LEGALL5_3 3
+#define DWT_DIRAC_DD13_7 4
+#define DWT_DIRAC_HAAR0 5
+#define DWT_DIRAC_HAAR1 6
+#define DWT_DIRAC_FIDELITY 7
+#define DWT_DIRAC_DAUB9_7 8
+
+void ff_spatial_idwt2(IDWTELEM *buffer, int width, int height, int stride,
+ int type, int decomposition_count);
+
+void ff_spatial_idwt_slice2(dwt_compose_t *cs, IDWTELEM *buffer, int width, int height,
+ int stride, int type, int decomposition_count, int y);
+
+#endif /* AVCODEC_DWT_H */
More information about the FFmpeg-soc
mailing list