• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/dwt.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2010 Michael Niedermayer <michaelni@gmx.at>
00003  * Copyright (C) 2008 David Conrad
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "libavutil/attributes.h"
00023 #include "dsputil.h"
00024 #include "dwt.h"
00025 #include "libavcodec/x86/dwt.h"
00026 
00027 void ff_slice_buffer_init(slice_buffer * buf, int line_count, int max_allocated_lines, int line_width, IDWTELEM * base_buffer)
00028 {
00029     int i;
00030 
00031     buf->base_buffer = base_buffer;
00032     buf->line_count  = line_count;
00033     buf->line_width  = line_width;
00034     buf->data_count  = max_allocated_lines;
00035     buf->line        = av_mallocz (sizeof(IDWTELEM *) * line_count);
00036     buf->data_stack  = av_malloc (sizeof(IDWTELEM *) * max_allocated_lines);
00037 
00038     for(i = 0; i < max_allocated_lines; i++){
00039         buf->data_stack[i] = av_malloc (sizeof(IDWTELEM) * line_width);
00040     }
00041 
00042     buf->data_stack_top = max_allocated_lines - 1;
00043 }
00044 
00045 IDWTELEM * ff_slice_buffer_load_line(slice_buffer * buf, int line)
00046 {
00047     IDWTELEM * buffer;
00048 
00049     assert(buf->data_stack_top >= 0);
00050     if (buf->line[line])
00051         return buf->line[line];
00052 
00053     buffer = buf->data_stack[buf->data_stack_top];
00054     buf->data_stack_top--;
00055     buf->line[line] = buffer;
00056 
00057     return buffer;
00058 }
00059 
00060 void ff_slice_buffer_release(slice_buffer * buf, int line)
00061 {
00062     IDWTELEM * buffer;
00063 
00064     assert(line >= 0 && line < buf->line_count);
00065     assert(buf->line[line]);
00066 
00067     buffer = buf->line[line];
00068     buf->data_stack_top++;
00069     buf->data_stack[buf->data_stack_top] = buffer;
00070     buf->line[line] = NULL;
00071 }
00072 
00073 void ff_slice_buffer_flush(slice_buffer * buf)
00074 {
00075     int i;
00076     for(i = 0; i < buf->line_count; i++){
00077         if (buf->line[i])
00078             ff_slice_buffer_release(buf, i);
00079     }
00080 }
00081 
00082 void ff_slice_buffer_destroy(slice_buffer * buf)
00083 {
00084     int i;
00085     ff_slice_buffer_flush(buf);
00086 
00087     for(i = buf->data_count - 1; i >= 0; i--){
00088         av_freep(&buf->data_stack[i]);
00089     }
00090     av_freep(&buf->data_stack);
00091     av_freep(&buf->line);
00092 }
00093 
00094 static inline int mirror(int v, int m){
00095     while((unsigned)v > (unsigned)m){
00096         v = -v;
00097         if(v < 0) v+= 2*m;
00098     }
00099     return v;
00100 }
00101 
00102 static av_always_inline void
00103 lift(DWTELEM *dst, DWTELEM *src, DWTELEM *ref,
00104      int dst_step, int src_step, int ref_step,
00105      int width, int mul, int add, int shift,
00106      int highpass, int inverse){
00107     const int mirror_left  = !highpass;
00108     const int mirror_right = (width & 1) ^ highpass;
00109     const int w            = (width >> 1) - 1 + (highpass & width);
00110     int i;
00111 
00112 #define LIFT(src, ref, inv) ((src) + ((inv) ? - (ref) : + (ref)))
00113     if(mirror_left){
00114         dst[0] = LIFT(src[0], ((mul * 2 * ref[0] + add) >> shift), inverse);
00115         dst   += dst_step;
00116         src   += src_step;
00117     }
00118 
00119     for(i=0; i<w; i++){
00120         dst[i * dst_step] =
00121             LIFT(src[i * src_step],
00122                  ((mul * (ref[i * ref_step] + ref[(i + 1) * ref_step]) + add) >> shift),
00123                  inverse);
00124     }
00125 
00126     if(mirror_right){
00127         dst[w * dst_step] =
00128             LIFT(src[w * src_step],
00129                  ((mul * 2 * ref[w * ref_step] + add) >> shift),
00130                  inverse);
00131     }
00132 }
00133 
00134 static av_always_inline void
00135 inv_lift(IDWTELEM *dst, IDWTELEM *src, IDWTELEM *ref,
00136          int dst_step, int src_step, int ref_step,
00137          int width, int mul, int add, int shift,
00138          int highpass, int inverse){
00139     const int mirror_left  = !highpass;
00140     const int mirror_right = (width&1) ^ highpass;
00141     const int w            = (width >> 1) - 1 + (highpass & width);
00142     int i;
00143 
00144 #define LIFT(src, ref, inv) ((src) + ((inv) ? - (ref) : + (ref)))
00145     if(mirror_left){
00146         dst[0] =
00147             LIFT(src[0],
00148                  ((mul * 2 * ref[0] + add) >> shift),
00149                  inverse);
00150         dst   += dst_step;
00151         src   += src_step;
00152     }
00153 
00154     for(i = 0; i < w; i++){
00155         dst[i * dst_step] =
00156             LIFT(src[i * src_step],
00157                  ((mul * (ref[i * ref_step] + ref[(i + 1) * ref_step]) + add) >> shift),
00158                  inverse);
00159     }
00160 
00161     if(mirror_right){
00162         dst[w * dst_step] =
00163             LIFT(src[w * src_step],
00164                  ((mul * 2 * ref[w * ref_step] + add) >> shift),
00165                  inverse);
00166     }
00167 }
00168 
00169 #ifndef liftS
00170 static av_always_inline void
00171 liftS(DWTELEM *dst, DWTELEM *src, DWTELEM *ref,
00172       int dst_step, int src_step, int ref_step,
00173       int width, int mul, int add, int shift,
00174       int highpass, int inverse){
00175     const int mirror_left  = !highpass;
00176     const int mirror_right = (width&1) ^ highpass;
00177     const int w            = (width >> 1) - 1 + (highpass & width);
00178     int i;
00179 
00180     assert(shift == 4);
00181 #define LIFTS(src, ref, inv)                                            \
00182     ((inv) ?                                                            \
00183      (src) + (((ref) + 4 * (src)) >> shift):                            \
00184      -((-16 * (src) + (ref) + add / 4 + 1 + (5 << 25)) / (5 * 4) - (1 << 23)))
00185     if(mirror_left){
00186         dst[0] = LIFTS(src[0], mul * 2 * ref[0] + add, inverse);
00187         dst   += dst_step;
00188         src   += src_step;
00189     }
00190 
00191     for(i = 0; i < w; i++){
00192         dst[i * dst_step] =
00193             LIFTS(src[i * src_step],
00194                   mul * (ref[i * ref_step] + ref[(i+1) * ref_step]) + add,
00195                   inverse);
00196     }
00197 
00198     if(mirror_right){
00199         dst[w * dst_step] =
00200             LIFTS(src[w * src_step], mul * 2 * ref[w * ref_step] + add, inverse);
00201     }
00202 }
00203 static av_always_inline void
00204 inv_liftS(IDWTELEM *dst, IDWTELEM *src, IDWTELEM *ref,
00205           int dst_step, int src_step, int ref_step,
00206           int width, int mul, int add, int shift,
00207           int highpass, int inverse){
00208     const int mirror_left  = !highpass;
00209     const int mirror_right = (width&1) ^ highpass;
00210     const int w            = (width >> 1) - 1 + (highpass & width);
00211     int i;
00212 
00213     assert(shift == 4);
00214 #define LIFTS(src, ref, inv)                                            \
00215     ((inv) ?                                                            \
00216      (src) + (((ref) + 4 * (src)) >> shift):                            \
00217      -((-16 * (src) + (ref) + add / 4 + 1 + (5 << 25)) / (5 * 4) - (1 << 23)))
00218     if(mirror_left){
00219         dst[0] = LIFTS(src[0], mul * 2 * ref[0] + add, inverse);
00220         dst += dst_step;
00221         src += src_step;
00222     }
00223 
00224     for(i = 0; i < w; i++){
00225         dst[i * dst_step] =
00226             LIFTS(src[i * src_step],
00227                   mul * (ref[i * ref_step] + ref[(i+1) * ref_step]) + add,
00228                   inverse);
00229     }
00230 
00231     if(mirror_right){
00232         dst[w * dst_step] =
00233             LIFTS(src[w * src_step], mul * 2 * ref[w * ref_step] + add, inverse);
00234     }
00235 }
00236 #endif /* ! liftS */
00237 
00238 static void horizontal_decompose53i(DWTELEM *b, int width){
00239     DWTELEM temp[width];
00240     const int width2 = width>>1;
00241     const int w2     = (width+1)>>1;
00242     int x;
00243 
00244     for(x = 0; x < width2; x++){
00245         temp[x   ] = b[2 * x    ];
00246         temp[x+w2] = b[2 * x + 1];
00247     }
00248     if(width & 1)
00249         temp[x   ] = b[2 * x    ];
00250 #if 0
00251     {
00252     int A1,A2,A3,A4;
00253     A2  = temp[1       ];
00254     A4  = temp[0       ];
00255     A1  = temp[0+width2];
00256     A1 -= (A2 + A4) >> 1;
00257     A4 += (A1 + 1) >> 1;
00258     b[0 + width2] = A1;
00259     b[0       ]   = A4;
00260     for(x = 1; x + 1 < width2; x += 2){
00261         A3  = temp[x + width2];
00262         A4  = temp[x + 1     ];
00263         A3 -= (A2 + A4) >> 1;
00264         A2 += (A1 + A3 + 2) >> 2;
00265         b[x + width2] = A3;
00266         b[x         ] = A2;
00267 
00268         A1  = temp[x + 1 + width2];
00269         A2  = temp[x + 2         ];
00270         A1 -= (A2 + A4) >> 1;
00271         A4 += (A1 + A3 + 2) >> 2;
00272         b[x + 1 + width2] = A1;
00273         b[x + 1         ] = A4;
00274     }
00275     A3  = temp[width - 1];
00276     A3 -= A2;
00277     A2 += (A1 + A3 + 2) >> 2;
00278     b[width -1] = A3;
00279     b[width2-1] = A2;
00280     }
00281 #else
00282     lift(b + w2, temp + w2, temp, 1, 1, 1, width, -1, 0, 1, 1, 0);
00283     lift(b   , temp   , b + w2, 1, 1, 1, width,  1, 2, 2, 0, 0);
00284 #endif /* 0 */
00285 }
00286 
00287 static void vertical_decompose53iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){
00288     int i;
00289 
00290     for(i = 0; i < width; i++){
00291         b1[i] -= (b0[i] + b2[i]) >> 1;
00292     }
00293 }
00294 
00295 static void vertical_decompose53iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){
00296     int i;
00297 
00298     for(i = 0; i < width; i++){
00299         b1[i] += (b0[i] + b2[i] + 2) >> 2;
00300     }
00301 }
00302 
00303 static void spatial_decompose53i(DWTELEM *buffer, int width, int height, int stride){
00304     int y;
00305     DWTELEM *b0 = buffer + mirror(-2 - 1, height-1)*stride;
00306     DWTELEM *b1 = buffer + mirror(-2    , height-1)*stride;
00307 
00308     for(y = -2; y < height; y += 2){
00309         DWTELEM *b2 = buffer + mirror(y + 1, height-1) * stride;
00310         DWTELEM *b3 = buffer + mirror(y + 2, height-1) * stride;
00311 
00312         if(y + 1 < (unsigned)height) horizontal_decompose53i(b2, width);
00313         if(y + 2 < (unsigned)height) horizontal_decompose53i(b3, width);
00314 
00315         if(y + 1 < (unsigned)height) vertical_decompose53iH0(b1, b2, b3, width);
00316         if(y + 0 < (unsigned)height) vertical_decompose53iL0(b0, b1, b2, width);
00317 
00318         b0 = b2;
00319         b1 = b3;
00320     }
00321 }
00322 
00323 static void horizontal_decompose97i(DWTELEM *b, int width){
00324     DWTELEM temp[width];
00325     const int w2 = (width+1)>>1;
00326 
00327     lift (temp + w2, b    + 1 , b        , 1, 2, 2, width,  W_AM, W_AO, W_AS, 1, 1);
00328     liftS(temp     , b        , temp + w2, 1, 2, 1, width,  W_BM, W_BO, W_BS, 0, 0);
00329     lift (b    + w2, temp + w2, temp     , 1, 1, 1, width,  W_CM, W_CO, W_CS, 1, 0);
00330     lift (b        , temp     , b    + w2, 1, 1, 1, width,  W_DM, W_DO, W_DS, 0, 0);
00331 }
00332 
00333 
00334 static void vertical_decompose97iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){
00335     int i;
00336 
00337     for(i = 0; i < width; i++){
00338         b1[i] -= (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS;
00339     }
00340 }
00341 
00342 static void vertical_decompose97iH1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){
00343     int i;
00344 
00345     for(i=0; i < width; i++){
00346         b1[i] += (W_CM * (b0[i] + b2[i]) + W_CO) >> W_CS;
00347     }
00348 }
00349 
00350 static void vertical_decompose97iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){
00351     int i;
00352 
00353     for(i = 0; i < width; i++){
00354 #ifdef liftS
00355         b1[i] -= (W_BM * (b0[i] + b2[i]) + W_BO) >> W_BS;
00356 #else
00357         b1[i] = (16 * 4 * b1[i] - 4 * (b0[i] + b2[i]) + W_BO * 5 + (5 << 27)) / (5 * 16) - (1 << 23);
00358 #endif
00359     }
00360 }
00361 
00362 static void vertical_decompose97iL1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, int width){
00363     int i;
00364 
00365     for(i = 0; i < width; i++){
00366         b1[i] += (W_DM * (b0[i] + b2[i]) + W_DO) >> W_DS;
00367     }
00368 }
00369 
00370 static void spatial_decompose97i(DWTELEM *buffer, int width, int height, int stride){
00371     int y;
00372     DWTELEM *b0 = buffer + mirror(-4 - 1, height-1) * stride;
00373     DWTELEM *b1 = buffer + mirror(-4    , height-1) * stride;
00374     DWTELEM *b2 = buffer + mirror(-4 + 1, height-1) * stride;
00375     DWTELEM *b3 = buffer + mirror(-4 + 2, height-1) * stride;
00376 
00377     for(y = -4; y < height; y += 2){
00378         DWTELEM *b4 = buffer + mirror(y + 3, height-1) * stride;
00379         DWTELEM *b5 = buffer + mirror(y + 4, height-1) * stride;
00380 
00381         if(y + 3 < (unsigned)height) horizontal_decompose97i(b4, width);
00382         if(y + 4 < (unsigned)height) horizontal_decompose97i(b5, width);
00383 
00384         if(y + 3 < (unsigned)height) vertical_decompose97iH0(b3, b4, b5, width);
00385         if(y + 2 < (unsigned)height) vertical_decompose97iL0(b2, b3, b4, width);
00386         if(y + 1 < (unsigned)height) vertical_decompose97iH1(b1, b2, b3, width);
00387         if(y + 0 < (unsigned)height) vertical_decompose97iL1(b0, b1, b2, width);
00388 
00389         b0 = b2;
00390         b1 = b3;
00391         b2 = b4;
00392         b3 = b5;
00393     }
00394 }
00395 
00396 void ff_spatial_dwt(DWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count){
00397     int level;
00398 
00399     for(level = 0; level < decomposition_count; level++){
00400         switch(type){
00401         case DWT_97: spatial_decompose97i(buffer, width >> level, height >> level, stride << level); break;
00402         case DWT_53: spatial_decompose53i(buffer, width >> level, height >> level, stride << level); break;
00403         }
00404     }
00405 }
00406 
00407 static void horizontal_compose53i(IDWTELEM *b, int width){
00408     IDWTELEM temp[width];
00409     const int width2 = width       >> 1;
00410     const int w2     = (width + 1) >> 1;
00411     int x;
00412 
00413     for(x = 0; x < width2; x++){
00414         temp[2 * x    ] = b[x     ];
00415         temp[2 * x + 1] = b[x + w2];
00416     }
00417     if(width & 1)
00418         temp[2 * x    ] = b[x   ];
00419 
00420     b[0] = temp[0] - ((temp[1] + 1) >> 1);
00421     for(x = 2; x < width - 1; x += 2){
00422         b[x    ] = temp[x    ] - ((temp[x - 1] + temp[x + 1] + 2) >> 2);
00423         b[x - 1] = temp[x - 1] + ((b   [x - 2] + b   [x  ] + 1) >> 1);
00424     }
00425     if(width & 1){
00426         b[x    ] = temp[x    ] - ((temp[x - 1] + 1) >> 1);
00427         b[x - 1] = temp[x - 1] + ((b   [x - 2] + b  [x  ] + 1) >> 1);
00428     }else
00429         b[x - 1] = temp[x - 1] + b[x - 2];
00430 }
00431 
00432 static void vertical_compose53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){
00433     int i;
00434 
00435     for(i = 0; i < width; i++){
00436         b1[i] += (b0[i] + b2[i]) >> 1;
00437     }
00438 }
00439 
00440 static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){
00441     int i;
00442 
00443     for(i = 0; i < width; i++){
00444         b1[i] -= (b0[i] + b2[i] + 2) >> 2;
00445     }
00446 }
00447 
00448 static void spatial_compose53i_buffered_init(DWTCompose *cs, slice_buffer * sb, int height, int stride_line){
00449     cs->b0 = slice_buffer_get_line(sb, mirror(-1-1, height - 1) * stride_line);
00450     cs->b1 = slice_buffer_get_line(sb, mirror(-1  , height - 1) * stride_line);
00451     cs->y  = -1;
00452 }
00453 
00454 static void spatial_compose53i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride){
00455     cs->b0 = buffer + mirror(-1-1, height - 1) * stride;
00456     cs->b1 = buffer + mirror(-1  , height - 1) * stride;
00457     cs->y  = -1;
00458 }
00459 
00460 static void spatial_compose53i_dy_buffered(DWTCompose *cs, slice_buffer * sb, int width, int height, int stride_line){
00461     int y        = cs->y;
00462     IDWTELEM *b0 = cs->b0;
00463     IDWTELEM *b1 = cs->b1;
00464     IDWTELEM *b2 = slice_buffer_get_line(sb, mirror(y + 1, height-1) * stride_line);
00465     IDWTELEM *b3 = slice_buffer_get_line(sb, mirror(y + 2, height-1) * stride_line);
00466 
00467     if(y + 1 < (unsigned)height && y < (unsigned)height){
00468         int x;
00469 
00470         for(x = 0; x < width; x++){
00471             b2[x] -= (b1[x] + b3[x] + 2) >> 2;
00472             b1[x] += (b0[x] + b2[x]) >> 1;
00473         }
00474     }else{
00475         if(y + 1 < (unsigned)height) vertical_compose53iL0(b1, b2, b3, width);
00476         if(y + 0 < (unsigned)height) vertical_compose53iH0(b0, b1, b2, width);
00477     }
00478 
00479         if(y - 1 <(unsigned)height) horizontal_compose53i(b0, width);
00480         if(y + 0 <(unsigned)height) horizontal_compose53i(b1, width);
00481 
00482     cs->b0 = b2;
00483     cs->b1 = b3;
00484     cs->y += 2;
00485 }
00486 
00487 static void spatial_compose53i_dy(DWTCompose *cs, IDWTELEM *buffer, int width, int height, int stride){
00488     int y        = cs->y;
00489     IDWTELEM *b0 = cs->b0;
00490     IDWTELEM *b1 = cs->b1;
00491     IDWTELEM *b2 = buffer + mirror(y + 1, height - 1) * stride;
00492     IDWTELEM *b3 = buffer + mirror(y + 2, height - 1) * stride;
00493 
00494         if(y + 1 < (unsigned)height) vertical_compose53iL0(b1, b2, b3, width);
00495         if(y + 0 < (unsigned)height) vertical_compose53iH0(b0, b1, b2, width);
00496 
00497         if(y - 1 < (unsigned)height) horizontal_compose53i(b0, width);
00498         if(y + 0 < (unsigned)height) horizontal_compose53i(b1, width);
00499 
00500     cs->b0 = b2;
00501     cs->b1 = b3;
00502     cs->y += 2;
00503 }
00504 
00505 static void av_unused spatial_compose53i(IDWTELEM *buffer, int width, int height, int stride){
00506     DWTCompose cs;
00507     spatial_compose53i_init(&cs, buffer, height, stride);
00508     while(cs.y <= height)
00509         spatial_compose53i_dy(&cs, buffer, width, height, stride);
00510 }
00511 
00512 
00513 void ff_snow_horizontal_compose97i(IDWTELEM *b, int width){
00514     IDWTELEM temp[width];
00515     const int w2 = (width + 1) >> 1;
00516 
00517 #if 0 //maybe more understadable but slower
00518     inv_lift (temp    , b      , b  + w2, 2, 1, 1, width,  W_DM, W_DO, W_DS, 0, 1);
00519     inv_lift (temp + 1, b  + w2, temp   , 2, 1, 2, width,  W_CM, W_CO, W_CS, 1, 1);
00520 
00521     inv_liftS(b      ,temp    ,temp + 1, 2, 2, 2, width,  W_BM, W_BO, W_BS, 0, 1);
00522     inv_lift (b + 1  ,temp + 1,b       , 2, 2, 2, width,  W_AM, W_AO, W_AS, 1, 0);
00523 #else
00524     int x;
00525     temp[0] = b[0] - ((3 * b[w2] + 2) >> 2);
00526     for(x = 1; x < (width >> 1); x++){
00527         temp[2 * x    ] = b[x         ] - (( 3 * (b   [ x + w2 - 1] + b[x + w2]) + 4) >> 3);
00528         temp[2 * x - 1] = b[x + w2 - 1] - temp[2 * x - 2] - temp[2 * x];
00529     }
00530     if(width & 1){
00531         temp[2*x  ] = b[x     ] - ((3*b   [x+w2-1]+2)>>2);
00532         temp[2*x-1] = b[x+w2-1] - temp[2*x-2] - temp[2*x];
00533     }else
00534         temp[2*x-1] = b[x+w2-1] - 2*temp[2*x-2];
00535 
00536     b[0] = temp[0] + ((2*temp[0] + temp[1]+4)>>3);
00537     for(x=2; x<width-1; x+=2){
00538         b[x  ] = temp[x  ] + ((4*temp[x  ] + temp[x-1] + temp[x+1]+8)>>4);
00539         b[x-1] = temp[x-1] + ((3*(b  [x-2] + b   [x  ] ))>>1);
00540     }
00541     if(width&1){
00542         b[x  ] = temp[x  ] + ((2*temp[x  ] + temp[x-1]+4)>>3);
00543         b[x-1] = temp[x-1] + ((3*(b  [x-2] + b   [x  ] ))>>1);
00544     }else
00545         b[x-1] = temp[x-1] + 3*b [x-2];
00546 #endif
00547 }
00548 
00549 static void vertical_compose97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){
00550     int i;
00551 
00552     for(i=0; i<width; i++){
00553         b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS;
00554     }
00555 }
00556 
00557 static void vertical_compose97iH1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){
00558     int i;
00559 
00560     for(i=0; i<width; i++){
00561         b1[i] -= (W_CM*(b0[i] + b2[i])+W_CO)>>W_CS;
00562     }
00563 }
00564 
00565 static void vertical_compose97iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){
00566     int i;
00567 
00568     for(i=0; i<width; i++){
00569 #ifdef liftS
00570         b1[i] += (W_BM*(b0[i] + b2[i])+W_BO)>>W_BS;
00571 #else
00572         b1[i] += (W_BM*(b0[i] + b2[i])+4*b1[i]+W_BO)>>W_BS;
00573 #endif
00574     }
00575 }
00576 
00577 static void vertical_compose97iL1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width){
00578     int i;
00579 
00580     for(i=0; i<width; i++){
00581         b1[i] -= (W_DM*(b0[i] + b2[i])+W_DO)>>W_DS;
00582     }
00583 }
00584 
00585 void ff_snow_vertical_compose97i(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, int width){
00586     int i;
00587 
00588     for(i=0; i<width; i++){
00589         b4[i] -= (W_DM*(b3[i] + b5[i])+W_DO)>>W_DS;
00590         b3[i] -= (W_CM*(b2[i] + b4[i])+W_CO)>>W_CS;
00591 #ifdef liftS
00592         b2[i] += (W_BM*(b1[i] + b3[i])+W_BO)>>W_BS;
00593 #else
00594         b2[i] += (W_BM*(b1[i] + b3[i])+4*b2[i]+W_BO)>>W_BS;
00595 #endif
00596         b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS;
00597     }
00598 }
00599 
00600 static void spatial_compose97i_buffered_init(DWTCompose *cs, slice_buffer * sb, int height, int stride_line){
00601     cs->b0 = slice_buffer_get_line(sb, mirror(-3-1, height-1) * stride_line);
00602     cs->b1 = slice_buffer_get_line(sb, mirror(-3  , height-1) * stride_line);
00603     cs->b2 = slice_buffer_get_line(sb, mirror(-3+1, height-1) * stride_line);
00604     cs->b3 = slice_buffer_get_line(sb, mirror(-3+2, height-1) * stride_line);
00605     cs->y = -3;
00606 }
00607 
00608 static void spatial_compose97i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride){
00609     cs->b0 = buffer + mirror(-3-1, height-1)*stride;
00610     cs->b1 = buffer + mirror(-3  , height-1)*stride;
00611     cs->b2 = buffer + mirror(-3+1, height-1)*stride;
00612     cs->b3 = buffer + mirror(-3+2, height-1)*stride;
00613     cs->y = -3;
00614 }
00615 
00616 static void spatial_compose97i_dy_buffered(DWTContext *dsp, DWTCompose *cs, slice_buffer * sb, int width, int height, int stride_line){
00617     int y = cs->y;
00618 
00619     IDWTELEM *b0= cs->b0;
00620     IDWTELEM *b1= cs->b1;
00621     IDWTELEM *b2= cs->b2;
00622     IDWTELEM *b3= cs->b3;
00623     IDWTELEM *b4= slice_buffer_get_line(sb, mirror(y + 3, height - 1) * stride_line);
00624     IDWTELEM *b5= slice_buffer_get_line(sb, mirror(y + 4, height - 1) * stride_line);
00625 
00626     if(y>0 && y+4<height){
00627         dsp->vertical_compose97i(b0, b1, b2, b3, b4, b5, width);
00628     }else{
00629         if(y+3<(unsigned)height) vertical_compose97iL1(b3, b4, b5, width);
00630         if(y+2<(unsigned)height) vertical_compose97iH1(b2, b3, b4, width);
00631         if(y+1<(unsigned)height) vertical_compose97iL0(b1, b2, b3, width);
00632         if(y+0<(unsigned)height) vertical_compose97iH0(b0, b1, b2, width);
00633     }
00634 
00635     if(y-1<(unsigned)height) dsp->horizontal_compose97i(b0, width);
00636     if(y+0<(unsigned)height) dsp->horizontal_compose97i(b1, width);
00637 
00638     cs->b0=b2;
00639     cs->b1=b3;
00640     cs->b2=b4;
00641     cs->b3=b5;
00642     cs->y += 2;
00643 }
00644 
00645 static void spatial_compose97i_dy(DWTCompose *cs, IDWTELEM *buffer, int width, int height, int stride){
00646     int y = cs->y;
00647     IDWTELEM *b0= cs->b0;
00648     IDWTELEM *b1= cs->b1;
00649     IDWTELEM *b2= cs->b2;
00650     IDWTELEM *b3= cs->b3;
00651     IDWTELEM *b4= buffer + mirror(y+3, height-1)*stride;
00652     IDWTELEM *b5= buffer + mirror(y+4, height-1)*stride;
00653 
00654     if(y+3<(unsigned)height) vertical_compose97iL1(b3, b4, b5, width);
00655     if(y+2<(unsigned)height) vertical_compose97iH1(b2, b3, b4, width);
00656     if(y+1<(unsigned)height) vertical_compose97iL0(b1, b2, b3, width);
00657     if(y+0<(unsigned)height) vertical_compose97iH0(b0, b1, b2, width);
00658 
00659     if(y-1<(unsigned)height) ff_snow_horizontal_compose97i(b0, width);
00660     if(y+0<(unsigned)height) ff_snow_horizontal_compose97i(b1, width);
00661 
00662     cs->b0=b2;
00663     cs->b1=b3;
00664     cs->b2=b4;
00665     cs->b3=b5;
00666     cs->y += 2;
00667 }
00668 
00669 static void av_unused spatial_compose97i(IDWTELEM *buffer, int width, int height, int stride){
00670     DWTCompose cs;
00671     spatial_compose97i_init(&cs, buffer, height, stride);
00672     while(cs.y <= height)
00673         spatial_compose97i_dy(&cs, buffer, width, height, stride);
00674 }
00675 
00676 void ff_spatial_idwt_buffered_init(DWTCompose *cs, slice_buffer * sb, int width, int height, int stride_line, int type, int decomposition_count){
00677     int level;
00678     for(level=decomposition_count-1; level>=0; level--){
00679         switch(type){
00680         case DWT_97: spatial_compose97i_buffered_init(cs+level, sb, height>>level, stride_line<<level); break;
00681         case DWT_53: spatial_compose53i_buffered_init(cs+level, sb, height>>level, stride_line<<level); break;
00682         }
00683     }
00684 }
00685 
00686 void ff_spatial_idwt_buffered_slice(DWTContext *dsp, DWTCompose *cs, slice_buffer * slice_buf, int width, int height, int stride_line, int type, int decomposition_count, int y){
00687     const int support = type==1 ? 3 : 5;
00688     int level;
00689     if(type==2) return;
00690 
00691     for(level=decomposition_count-1; level>=0; level--){
00692         while(cs[level].y <= FFMIN((y>>level)+support, height>>level)){
00693             switch(type){
00694             case DWT_97: spatial_compose97i_dy_buffered(dsp, cs+level, slice_buf, width>>level, height>>level, stride_line<<level);
00695                 break;
00696             case DWT_53: spatial_compose53i_dy_buffered(cs+level, slice_buf, width>>level, height>>level, stride_line<<level);
00697                 break;
00698             }
00699         }
00700     }
00701 }
00702 
00703 static void ff_spatial_idwt_init(DWTCompose *cs, IDWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count){
00704     int level;
00705     for(level=decomposition_count-1; level>=0; level--){
00706         switch(type){
00707         case DWT_97: spatial_compose97i_init(cs+level, buffer, height>>level, stride<<level); break;
00708         case DWT_53: spatial_compose53i_init(cs+level, buffer, height>>level, stride<<level); break;
00709         }
00710     }
00711 }
00712 
00713 static void ff_spatial_idwt_slice(DWTCompose *cs, IDWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count, int y){
00714     const int support = type==1 ? 3 : 5;
00715     int level;
00716     if(type==2) return;
00717 
00718     for(level=decomposition_count-1; level>=0; level--){
00719         while(cs[level].y <= FFMIN((y>>level)+support, height>>level)){
00720             switch(type){
00721             case DWT_97: spatial_compose97i_dy(cs+level, buffer, width>>level, height>>level, stride<<level);
00722                 break;
00723             case DWT_53: spatial_compose53i_dy(cs+level, buffer, width>>level, height>>level, stride<<level);
00724                 break;
00725             }
00726         }
00727     }
00728 }
00729 
00730 void ff_spatial_idwt(IDWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count){
00731         DWTCompose cs[MAX_DECOMPOSITIONS];
00732         int y;
00733         ff_spatial_idwt_init(cs, buffer, width, height, stride, type, decomposition_count);
00734         for(y=0; y<height; y+=4)
00735             ff_spatial_idwt_slice(cs, buffer, width, height, stride, type, decomposition_count, y);
00736 }
00737 
00738 static inline int w_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int w, int h, int type){
00739     int s, i, j;
00740     const int dec_count= w==8 ? 3 : 4;
00741     int tmp[32*32];
00742     int level, ori;
00743     static const int scale[2][2][4][4]={
00744       {
00745         {
00746             // 9/7 8x8 dec=3
00747             {268, 239, 239, 213},
00748             {  0, 224, 224, 152},
00749             {  0, 135, 135, 110},
00750         },{
00751             // 9/7 16x16 or 32x32 dec=4
00752             {344, 310, 310, 280},
00753             {  0, 320, 320, 228},
00754             {  0, 175, 175, 136},
00755             {  0, 129, 129, 102},
00756         }
00757       },{
00758         {
00759             // 5/3 8x8 dec=3
00760             {275, 245, 245, 218},
00761             {  0, 230, 230, 156},
00762             {  0, 138, 138, 113},
00763         },{
00764             // 5/3 16x16 or 32x32 dec=4
00765             {352, 317, 317, 286},
00766             {  0, 328, 328, 233},
00767             {  0, 180, 180, 140},
00768             {  0, 132, 132, 105},
00769         }
00770       }
00771     };
00772 
00773     for (i = 0; i < h; i++) {
00774         for (j = 0; j < w; j+=4) {
00775             tmp[32*i+j+0] = (pix1[j+0] - pix2[j+0])<<4;
00776             tmp[32*i+j+1] = (pix1[j+1] - pix2[j+1])<<4;
00777             tmp[32*i+j+2] = (pix1[j+2] - pix2[j+2])<<4;
00778             tmp[32*i+j+3] = (pix1[j+3] - pix2[j+3])<<4;
00779         }
00780         pix1 += line_size;
00781         pix2 += line_size;
00782     }
00783 
00784     ff_spatial_dwt(tmp, w, h, 32, type, dec_count);
00785 
00786     s=0;
00787     assert(w==h);
00788     for(level=0; level<dec_count; level++){
00789         for(ori= level ? 1 : 0; ori<4; ori++){
00790             int size= w>>(dec_count-level);
00791             int sx= (ori&1) ? size : 0;
00792             int stride= 32<<(dec_count-level);
00793             int sy= (ori&2) ? stride>>1 : 0;
00794 
00795             for(i=0; i<size; i++){
00796                 for(j=0; j<size; j++){
00797                     int v= tmp[sx + sy + i*stride + j] * scale[type][dec_count-3][level][ori];
00798                     s += FFABS(v);
00799                 }
00800             }
00801         }
00802     }
00803     assert(s>=0);
00804     return s>>9;
00805 }
00806 
00807 static int w53_8_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h){
00808     return w_c(v, pix1, pix2, line_size,  8, h, 1);
00809 }
00810 
00811 static int w97_8_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h){
00812     return w_c(v, pix1, pix2, line_size,  8, h, 0);
00813 }
00814 
00815 static int w53_16_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h){
00816     return w_c(v, pix1, pix2, line_size, 16, h, 1);
00817 }
00818 
00819 static int w97_16_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h){
00820     return w_c(v, pix1, pix2, line_size, 16, h, 0);
00821 }
00822 
00823 int ff_w53_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h){
00824     return w_c(v, pix1, pix2, line_size, 32, h, 1);
00825 }
00826 
00827 int ff_w97_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h){
00828     return w_c(v, pix1, pix2, line_size, 32, h, 0);
00829 }
00830 
00831 void ff_dsputil_init_dwt(DSPContext *c)
00832 {
00833     c->w53[0]= w53_16_c;
00834     c->w53[1]= w53_8_c;
00835     c->w97[0]= w97_16_c;
00836     c->w97[1]= w97_8_c;
00837 }
00838 
00839 void ff_dwt_init(DWTContext *c)
00840 {
00841     c->vertical_compose97i = ff_snow_vertical_compose97i;
00842     c->horizontal_compose97i = ff_snow_horizontal_compose97i;
00843     c->inner_add_yblock = ff_snow_inner_add_yblock;
00844 
00845     if (HAVE_MMX) ff_dwt_init_x86(c);
00846 }
00847 
00848 
00849 static av_always_inline
00850 void interleave(IDWTELEM *dst, IDWTELEM *src0, IDWTELEM *src1, int w2, int add, int shift)
00851 {
00852     int i;
00853     for (i = 0; i < w2; i++) {
00854         dst[2*i  ] = (src0[i] + add) >> shift;
00855         dst[2*i+1] = (src1[i] + add) >> shift;
00856     }
00857 }
00858 
00859 static void horizontal_compose_dirac53i(IDWTELEM *b, IDWTELEM *temp, int w)
00860 {
00861     const int w2 = w >> 1;
00862     int x;
00863 
00864     temp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
00865     for (x = 1; x < w2; x++) {
00866         temp[x     ] = COMPOSE_53iL0     (b[x+w2-1], b[x     ], b[x+w2]);
00867         temp[x+w2-1] = COMPOSE_DIRAC53iH0(temp[x-1], b[x+w2-1], temp[x]);
00868     }
00869     temp[w-1] = COMPOSE_DIRAC53iH0(temp[w2-1], b[w-1], temp[w2-1]);
00870 
00871     interleave(b, temp, temp+w2, w2, 1, 1);
00872 }
00873 
00874 static void horizontal_compose_dd97i(IDWTELEM *b, IDWTELEM *tmp, int w)
00875 {
00876     const int w2 = w >> 1;
00877     int x;
00878 
00879     tmp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
00880     for (x = 1; x < w2; x++)
00881         tmp[x] = COMPOSE_53iL0(b[x+w2-1], b[x], b[x+w2]);
00882 
00883     // extend the edges
00884     tmp[-1]   = tmp[0];
00885     tmp[w2+1] = tmp[w2] = tmp[w2-1];
00886 
00887     for (x = 0; x < w2; x++) {
00888         b[2*x  ] = (tmp[x] + 1)>>1;
00889         b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
00890     }
00891 }
00892 
00893 static void horizontal_compose_dd137i(IDWTELEM *b, IDWTELEM *tmp, int w)
00894 {
00895     const int w2 = w >> 1;
00896     int x;
00897 
00898     tmp[0] = COMPOSE_DD137iL0(b[w2], b[w2], b[0], b[w2  ], b[w2+1]);
00899     tmp[1] = COMPOSE_DD137iL0(b[w2], b[w2], b[1], b[w2+1], b[w2+2]);
00900     for (x = 2; x < w2-1; x++)
00901         tmp[x] = COMPOSE_DD137iL0(b[x+w2-2], b[x+w2-1], b[x], b[x+w2], b[x+w2+1]);
00902     tmp[w2-1] = COMPOSE_DD137iL0(b[w-3], b[w-2], b[w2-1], b[w-1], b[w-1]);
00903 
00904     // extend the edges
00905     tmp[-1]   = tmp[0];
00906     tmp[w2+1] = tmp[w2] = tmp[w2-1];
00907 
00908     for (x = 0; x < w2; x++) {
00909         b[2*x  ] = (tmp[x] + 1)>>1;
00910         b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
00911     }
00912 }
00913 
00914 static av_always_inline
00915 void horizontal_compose_haari(IDWTELEM *b, IDWTELEM *temp, int w, int shift)
00916 {
00917     const int w2 = w >> 1;
00918     int x;
00919 
00920     for (x = 0; x < w2; x++) {
00921         temp[x   ] = COMPOSE_HAARiL0(b[x   ], b[x+w2]);
00922         temp[x+w2] = COMPOSE_HAARiH0(b[x+w2], temp[x]);
00923     }
00924 
00925     interleave(b, temp, temp+w2, w2, shift, shift);
00926 }
00927 
00928 static void horizontal_compose_haar0i(IDWTELEM *b, IDWTELEM *temp, int w)
00929 {
00930     horizontal_compose_haari(b, temp, w, 0);
00931 }
00932 
00933 static void horizontal_compose_haar1i(IDWTELEM *b, IDWTELEM *temp, int w)
00934 {
00935     horizontal_compose_haari(b, temp, w, 1);
00936 }
00937 
00938 static void horizontal_compose_fidelityi(IDWTELEM *b, IDWTELEM *tmp, int w)
00939 {
00940     const int w2 = w >> 1;
00941     int i, x;
00942     IDWTELEM v[8];
00943 
00944     for (x = 0; x < w2; x++) {
00945         for (i = 0; i < 8; i++)
00946             v[i] = b[av_clip(x-3+i, 0, w2-1)];
00947         tmp[x] = COMPOSE_FIDELITYiH0(v[0], v[1], v[2], v[3], b[x+w2], v[4], v[5], v[6], v[7]);
00948     }
00949 
00950     for (x = 0; x < w2; x++) {
00951         for (i = 0; i < 8; i++)
00952             v[i] = tmp[av_clip(x-4+i, 0, w2-1)];
00953         tmp[x+w2] = COMPOSE_FIDELITYiL0(v[0], v[1], v[2], v[3], b[x], v[4], v[5], v[6], v[7]);
00954     }
00955 
00956     interleave(b, tmp+w2, tmp, w2, 0, 0);
00957 }
00958 
00959 static void horizontal_compose_daub97i(IDWTELEM *b, IDWTELEM *temp, int w)
00960 {
00961     const int w2 = w >> 1;
00962     int x, b0, b1, b2;
00963 
00964     temp[0] = COMPOSE_DAUB97iL1(b[w2], b[0], b[w2]);
00965     for (x = 1; x < w2; x++) {
00966         temp[x     ] = COMPOSE_DAUB97iL1(b[x+w2-1], b[x     ], b[x+w2]);
00967         temp[x+w2-1] = COMPOSE_DAUB97iH1(temp[x-1], b[x+w2-1], temp[x]);
00968     }
00969     temp[w-1] = COMPOSE_DAUB97iH1(temp[w2-1], b[w-1], temp[w2-1]);
00970 
00971     // second stage combined with interleave and shift
00972     b0 = b2 = COMPOSE_DAUB97iL0(temp[w2], temp[0], temp[w2]);
00973     b[0] = (b0 + 1) >> 1;
00974     for (x = 1; x < w2; x++) {
00975         b2 = COMPOSE_DAUB97iL0(temp[x+w2-1], temp[x     ], temp[x+w2]);
00976         b1 = COMPOSE_DAUB97iH0(          b0, temp[x+w2-1], b2        );
00977         b[2*x-1] = (b1 + 1) >> 1;
00978         b[2*x  ] = (b2 + 1) >> 1;
00979         b0 = b2;
00980     }
00981     b[w-1] = (COMPOSE_DAUB97iH0(b2, temp[w-1], b2) + 1) >> 1;
00982 }
00983 
00984 static void vertical_compose_dirac53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
00985 {
00986     int i;
00987 
00988     for(i=0; i<width; i++){
00989         b1[i] = COMPOSE_DIRAC53iH0(b0[i], b1[i], b2[i]);
00990     }
00991 }
00992 
00993 static void vertical_compose_dd97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
00994                                   IDWTELEM *b3, IDWTELEM *b4, int width)
00995 {
00996     int i;
00997 
00998     for(i=0; i<width; i++){
00999         b2[i] = COMPOSE_DD97iH0(b0[i], b1[i], b2[i], b3[i], b4[i]);
01000     }
01001 }
01002 
01003 static void vertical_compose_dd137iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
01004                                       IDWTELEM *b3, IDWTELEM *b4, int width)
01005 {
01006     int i;
01007 
01008     for(i=0; i<width; i++){
01009         b2[i] = COMPOSE_DD137iL0(b0[i], b1[i], b2[i], b3[i], b4[i]);
01010     }
01011 }
01012 
01013 static void vertical_compose_haar(IDWTELEM *b0, IDWTELEM *b1, int width)
01014 {
01015     int i;
01016 
01017     for (i = 0; i < width; i++) {
01018         b0[i] = COMPOSE_HAARiL0(b0[i], b1[i]);
01019         b1[i] = COMPOSE_HAARiH0(b1[i], b0[i]);
01020     }
01021 }
01022 
01023 static void vertical_compose_fidelityiH0(IDWTELEM *dst, IDWTELEM *b[8], int width)
01024 {
01025     int i;
01026 
01027     for(i=0; i<width; i++){
01028         dst[i] = COMPOSE_FIDELITYiH0(b[0][i], b[1][i], b[2][i], b[3][i], dst[i], b[4][i], b[5][i], b[6][i], b[7][i]);
01029     }
01030 }
01031 
01032 static void vertical_compose_fidelityiL0(IDWTELEM *dst, IDWTELEM *b[8], int width)
01033 {
01034     int i;
01035 
01036     for(i=0; i<width; i++){
01037         dst[i] = COMPOSE_FIDELITYiL0(b[0][i], b[1][i], b[2][i], b[3][i], dst[i], b[4][i], b[5][i], b[6][i], b[7][i]);
01038     }
01039 }
01040 
01041 static void vertical_compose_daub97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
01042 {
01043     int i;
01044 
01045     for(i=0; i<width; i++){
01046         b1[i] = COMPOSE_DAUB97iH0(b0[i], b1[i], b2[i]);
01047     }
01048 }
01049 
01050 static void vertical_compose_daub97iH1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
01051 {
01052     int i;
01053 
01054     for(i=0; i<width; i++){
01055         b1[i] = COMPOSE_DAUB97iH1(b0[i], b1[i], b2[i]);
01056     }
01057 }
01058 
01059 static void vertical_compose_daub97iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
01060 {
01061     int i;
01062 
01063     for(i=0; i<width; i++){
01064         b1[i] = COMPOSE_DAUB97iL0(b0[i], b1[i], b2[i]);
01065     }
01066 }
01067 
01068 static void vertical_compose_daub97iL1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
01069 {
01070     int i;
01071 
01072     for(i=0; i<width; i++){
01073         b1[i] = COMPOSE_DAUB97iL1(b0[i], b1[i], b2[i]);
01074     }
01075 }
01076 
01077 
01078 static void spatial_compose_dd97i_dy(DWTContext *d, int level, int width, int height, int stride)
01079 {
01080     vertical_compose_3tap vertical_compose_l0 = d->vertical_compose_l0;
01081     vertical_compose_5tap vertical_compose_h0 = d->vertical_compose_h0;
01082     DWTCompose *cs = d->cs + level;
01083 
01084     int i, y = cs->y;
01085     IDWTELEM *b[8];
01086     for (i = 0; i < 6; i++)
01087         b[i] = cs->b[i];
01088     b[6] = d->buffer + av_clip(y+5, 0, height-2)*stride;
01089     b[7] = d->buffer + av_clip(y+6, 1, height-1)*stride;
01090 
01091         if(y+5<(unsigned)height) vertical_compose_l0(      b[5], b[6], b[7],       width);
01092         if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
01093 
01094         if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
01095         if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
01096 
01097     for (i = 0; i < 6; i++)
01098         cs->b[i] = b[i+2];
01099     cs->y += 2;
01100 }
01101 
01102 static void spatial_compose_dirac53i_dy(DWTContext *d, int level, int width, int height, int stride)
01103 {
01104     vertical_compose_3tap vertical_compose_l0 = d->vertical_compose_l0;
01105     vertical_compose_3tap vertical_compose_h0 = d->vertical_compose_h0;
01106     DWTCompose *cs = d->cs + level;
01107 
01108     int y= cs->y;
01109     IDWTELEM *b[4] = { cs->b[0], cs->b[1] };
01110     b[2] = d->buffer + mirror(y+1, height-1)*stride;
01111     b[3] = d->buffer + mirror(y+2, height-1)*stride;
01112 
01113         if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
01114         if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
01115 
01116         if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
01117         if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
01118 
01119     cs->b[0] = b[2];
01120     cs->b[1] = b[3];
01121     cs->y += 2;
01122 }
01123 
01124 
01125 static void spatial_compose_dd137i_dy(DWTContext *d, int level, int width, int height, int stride)
01126 {
01127     vertical_compose_5tap vertical_compose_l0 = d->vertical_compose_l0;
01128     vertical_compose_5tap vertical_compose_h0 = d->vertical_compose_h0;
01129     DWTCompose *cs = d->cs + level;
01130 
01131     int i, y = cs->y;
01132     IDWTELEM *b[10];
01133     for (i = 0; i < 8; i++)
01134         b[i] = cs->b[i];
01135     b[8] = d->buffer + av_clip(y+7, 0, height-2)*stride;
01136     b[9] = d->buffer + av_clip(y+8, 1, height-1)*stride;
01137 
01138         if(y+5<(unsigned)height) vertical_compose_l0(b[3], b[5], b[6], b[7], b[9], width);
01139         if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
01140 
01141         if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
01142         if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
01143 
01144     for (i = 0; i < 8; i++)
01145         cs->b[i] = b[i+2];
01146     cs->y += 2;
01147 }
01148 
01149 // haar makes the assumption that height is even (always true for dirac)
01150 static void spatial_compose_haari_dy(DWTContext *d, int level, int width, int height, int stride)
01151 {
01152     vertical_compose_2tap vertical_compose = d->vertical_compose;
01153     int y = d->cs[level].y;
01154     IDWTELEM *b0 = d->buffer + (y-1)*stride;
01155     IDWTELEM *b1 = d->buffer + (y  )*stride;
01156 
01157     vertical_compose(b0, b1, width);
01158     d->horizontal_compose(b0, d->temp, width);
01159     d->horizontal_compose(b1, d->temp, width);
01160 
01161     d->cs[level].y += 2;
01162 }
01163 
01164 // Don't do sliced idwt for fidelity; the 9 tap filter makes it a bit annoying
01165 // Fortunately, this filter isn't used in practice.
01166 static void spatial_compose_fidelity(DWTContext *d, int level, int width, int height, int stride)
01167 {
01168     vertical_compose_9tap vertical_compose_l0 = d->vertical_compose_l0;
01169     vertical_compose_9tap vertical_compose_h0 = d->vertical_compose_h0;
01170     int i, y;
01171     IDWTELEM *b[8];
01172 
01173     for (y = 1; y < height; y += 2) {
01174         for (i = 0; i < 8; i++)
01175             b[i] = d->buffer + av_clip((y-7 + 2*i), 0, height-2)*stride;
01176         vertical_compose_h0(d->buffer + y*stride, b, width);
01177     }
01178 
01179     for (y = 0; y < height; y += 2) {
01180         for (i = 0; i < 8; i++)
01181             b[i] = d->buffer + av_clip((y-7 + 2*i), 1, height-1)*stride;
01182         vertical_compose_l0(d->buffer + y*stride, b, width);
01183     }
01184 
01185     for (y = 0; y < height; y++)
01186         d->horizontal_compose(d->buffer + y*stride, d->temp, width);
01187 
01188     d->cs[level].y = height+1;
01189 }
01190 
01191 static void spatial_compose_daub97i_dy(DWTContext *d, int level, int width, int height, int stride)
01192 {
01193     vertical_compose_3tap vertical_compose_l0 = d->vertical_compose_l0;
01194     vertical_compose_3tap vertical_compose_h0 = d->vertical_compose_h0;
01195     vertical_compose_3tap vertical_compose_l1 = d->vertical_compose_l1;
01196     vertical_compose_3tap vertical_compose_h1 = d->vertical_compose_h1;
01197     DWTCompose *cs = d->cs + level;
01198 
01199     int i, y = cs->y;
01200     IDWTELEM *b[6];
01201     for (i = 0; i < 4; i++)
01202         b[i] = cs->b[i];
01203     b[4] = d->buffer + mirror(y+3, height-1)*stride;
01204     b[5] = d->buffer + mirror(y+4, height-1)*stride;
01205 
01206         if(y+3<(unsigned)height) vertical_compose_l1(b[3], b[4], b[5], width);
01207         if(y+2<(unsigned)height) vertical_compose_h1(b[2], b[3], b[4], width);
01208         if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
01209         if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
01210 
01211         if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
01212         if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
01213 
01214     for (i = 0; i < 4; i++)
01215         cs->b[i] = b[i+2];
01216     cs->y += 2;
01217 }
01218 
01219 
01220 static void spatial_compose97i_init2(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
01221 {
01222     cs->b[0] = buffer + mirror(-3-1, height-1)*stride;
01223     cs->b[1] = buffer + mirror(-3  , height-1)*stride;
01224     cs->b[2] = buffer + mirror(-3+1, height-1)*stride;
01225     cs->b[3] = buffer + mirror(-3+2, height-1)*stride;
01226     cs->y = -3;
01227 }
01228 
01229 static void spatial_compose53i_init2(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
01230 {
01231     cs->b[0] = buffer + mirror(-1-1, height-1)*stride;
01232     cs->b[1] = buffer + mirror(-1  , height-1)*stride;
01233     cs->y = -1;
01234 }
01235 
01236 static void spatial_compose_dd97i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
01237 {
01238     cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
01239     cs->b[1] = buffer + av_clip(-5  , 1, height-1)*stride;
01240     cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
01241     cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
01242     cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
01243     cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
01244     cs->y = -5;
01245 }
01246 
01247 static void spatial_compose_dd137i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
01248 {
01249     cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
01250     cs->b[1] = buffer + av_clip(-5  , 1, height-1)*stride;
01251     cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
01252     cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
01253     cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
01254     cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
01255     cs->b[6] = buffer + av_clip(-5+5, 0, height-2)*stride;
01256     cs->b[7] = buffer + av_clip(-5+6, 1, height-1)*stride;
01257     cs->y = -5;
01258 }
01259 
01260 int ff_spatial_idwt_init2(DWTContext *d, IDWTELEM *buffer, int width, int height,
01261                           int stride, enum dwt_type type, int decomposition_count,
01262                           IDWTELEM *temp)
01263 {
01264     int level;
01265 
01266     d->buffer = buffer;
01267     d->width = width;
01268     d->height = height;
01269     d->stride = stride;
01270     d->decomposition_count = decomposition_count;
01271     d->temp = temp + 8;
01272 
01273     for(level=decomposition_count-1; level>=0; level--){
01274         int hl = height >> level;
01275         int stride_l = stride << level;
01276 
01277         switch(type){
01278         case DWT_DIRAC_DD9_7:
01279             spatial_compose_dd97i_init(d->cs+level, buffer, hl, stride_l);
01280             break;
01281         case DWT_DIRAC_LEGALL5_3:
01282             spatial_compose53i_init2(d->cs+level, buffer, hl, stride_l);
01283             break;
01284         case DWT_DIRAC_DD13_7:
01285             spatial_compose_dd137i_init(d->cs+level, buffer, hl, stride_l);
01286             break;
01287         case DWT_DIRAC_HAAR0:
01288         case DWT_DIRAC_HAAR1:
01289             d->cs[level].y = 1;
01290             break;
01291         case DWT_DIRAC_DAUB9_7:
01292             spatial_compose97i_init2(d->cs+level, buffer, hl, stride_l);
01293             break;
01294         default:
01295             d->cs[level].y = 0;
01296             break;
01297         }
01298     }
01299 
01300     switch (type) {
01301     case DWT_DIRAC_DD9_7:
01302         d->spatial_compose = spatial_compose_dd97i_dy;
01303         d->vertical_compose_l0 = vertical_compose53iL0;
01304         d->vertical_compose_h0 = vertical_compose_dd97iH0;
01305         d->horizontal_compose = horizontal_compose_dd97i;
01306         d->support = 7;
01307         break;
01308     case DWT_DIRAC_LEGALL5_3:
01309         d->spatial_compose = spatial_compose_dirac53i_dy;
01310         d->vertical_compose_l0 = vertical_compose53iL0;
01311         d->vertical_compose_h0 = vertical_compose_dirac53iH0;
01312         d->horizontal_compose = horizontal_compose_dirac53i;
01313         d->support = 3;
01314         break;
01315     case DWT_DIRAC_DD13_7:
01316         d->spatial_compose = spatial_compose_dd137i_dy;
01317         d->vertical_compose_l0 = vertical_compose_dd137iL0;
01318         d->vertical_compose_h0 = vertical_compose_dd97iH0;
01319         d->horizontal_compose = horizontal_compose_dd137i;
01320         d->support = 7;
01321         break;
01322     case DWT_DIRAC_HAAR0:
01323     case DWT_DIRAC_HAAR1:
01324         d->spatial_compose = spatial_compose_haari_dy;
01325         d->vertical_compose = vertical_compose_haar;
01326         if (type == DWT_DIRAC_HAAR0)
01327             d->horizontal_compose = horizontal_compose_haar0i;
01328         else
01329             d->horizontal_compose = horizontal_compose_haar1i;
01330         d->support = 1;
01331         break;
01332     case DWT_DIRAC_FIDELITY:
01333         d->spatial_compose = spatial_compose_fidelity;
01334         d->vertical_compose_l0 = vertical_compose_fidelityiL0;
01335         d->vertical_compose_h0 = vertical_compose_fidelityiH0;
01336         d->horizontal_compose = horizontal_compose_fidelityi;
01337         break;
01338     case DWT_DIRAC_DAUB9_7:
01339         d->spatial_compose = spatial_compose_daub97i_dy;
01340         d->vertical_compose_l0 = vertical_compose_daub97iL0;
01341         d->vertical_compose_h0 = vertical_compose_daub97iH0;
01342         d->vertical_compose_l1 = vertical_compose_daub97iL1;
01343         d->vertical_compose_h1 = vertical_compose_daub97iH1;
01344         d->horizontal_compose = horizontal_compose_daub97i;
01345         d->support = 5;
01346         break;
01347     default:
01348         av_log(NULL, AV_LOG_ERROR, "Unknown wavelet type %d\n", type);
01349         return -1;
01350     }
01351 
01352     if (HAVE_MMX) ff_spatial_idwt_init_mmx(d, type);
01353 
01354     return 0;
01355 }
01356 
01357 void ff_spatial_idwt_slice2(DWTContext *d, int y)
01358 {
01359     int level, support = d->support;
01360 
01361     for (level = d->decomposition_count-1; level >= 0; level--) {
01362         int wl = d->width  >> level;
01363         int hl = d->height >> level;
01364         int stride_l = d->stride << level;
01365 
01366         while (d->cs[level].y <= FFMIN((y>>level)+support, hl))
01367             d->spatial_compose(d, level, wl, hl, stride_l);
01368     }
01369 }
01370 
01371 int ff_spatial_idwt2(IDWTELEM *buffer, int width, int height, int stride,
01372                      enum dwt_type type, int decomposition_count, IDWTELEM *temp)
01373 {
01374     DWTContext d;
01375     int y;
01376 
01377     if (ff_spatial_idwt_init2(&d, buffer, width, height, stride, type, decomposition_count, temp))
01378         return -1;
01379 
01380     for (y = 0; y < d.height; y += 4)
01381         ff_spatial_idwt_slice2(&d, y);
01382 
01383     return 0;
01384 }
Generated on Fri Feb 1 2013 14:34:33 for FFmpeg by doxygen 1.7.1