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