FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dirac_dwt.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2010 Michael Niedermayer <michaelni@gmx.at>
3  * Copyright (C) 2008 David Conrad
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/attributes.h"
23 #include "libavutil/avassert.h"
24 #include "libavutil/common.h"
25 #include "dirac_dwt.h"
27 
28 
29 static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
30  int width)
31 {
32  int i;
33 
34  for (i = 0; i < width; i++)
35  b1[i] -= (b0[i] + b2[i] + 2) >> 2;
36 }
37 
38 
39 static av_always_inline
40 void interleave(IDWTELEM *dst, IDWTELEM *src0, IDWTELEM *src1, int w2, int add, int shift)
41 {
42  int i;
43  for (i = 0; i < w2; i++) {
44  dst[2*i ] = (src0[i] + add) >> shift;
45  dst[2*i+1] = (src1[i] + add) >> shift;
46  }
47 }
48 
50 {
51  const int w2 = w >> 1;
52  int x;
53 
54  temp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
55  for (x = 1; x < w2; x++) {
56  temp[x ] = COMPOSE_53iL0 (b[x+w2-1], b[x ], b[x+w2]);
57  temp[x+w2-1] = COMPOSE_DIRAC53iH0(temp[x-1], b[x+w2-1], temp[x]);
58  }
59  temp[w-1] = COMPOSE_DIRAC53iH0(temp[w2-1], b[w-1], temp[w2-1]);
60 
61  interleave(b, temp, temp+w2, w2, 1, 1);
62 }
63 
64 static void horizontal_compose_dd97i(IDWTELEM *b, IDWTELEM *tmp, int w)
65 {
66  const int w2 = w >> 1;
67  int x;
68 
69  tmp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
70  for (x = 1; x < w2; x++)
71  tmp[x] = COMPOSE_53iL0(b[x+w2-1], b[x], b[x+w2]);
72 
73  // extend the edges
74  tmp[-1] = tmp[0];
75  tmp[w2+1] = tmp[w2] = tmp[w2-1];
76 
77  for (x = 0; x < w2; x++) {
78  b[2*x ] = (tmp[x] + 1)>>1;
79  b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
80  }
81 }
82 
83 static void horizontal_compose_dd137i(IDWTELEM *b, IDWTELEM *tmp, int w)
84 {
85  const int w2 = w >> 1;
86  int x;
87 
88  tmp[0] = COMPOSE_DD137iL0(b[w2], b[w2], b[0], b[w2 ], b[w2+1]);
89  tmp[1] = COMPOSE_DD137iL0(b[w2], b[w2], b[1], b[w2+1], b[w2+2]);
90  for (x = 2; x < w2-1; x++)
91  tmp[x] = COMPOSE_DD137iL0(b[x+w2-2], b[x+w2-1], b[x], b[x+w2], b[x+w2+1]);
92  tmp[w2-1] = COMPOSE_DD137iL0(b[w-3], b[w-2], b[w2-1], b[w-1], b[w-1]);
93 
94  // extend the edges
95  tmp[-1] = tmp[0];
96  tmp[w2+1] = tmp[w2] = tmp[w2-1];
97 
98  for (x = 0; x < w2; x++) {
99  b[2*x ] = (tmp[x] + 1)>>1;
100  b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
101  }
102 }
103 
104 static av_always_inline
106 {
107  const int w2 = w >> 1;
108  int x;
109 
110  for (x = 0; x < w2; x++) {
111  temp[x ] = COMPOSE_HAARiL0(b[x ], b[x+w2]);
112  temp[x+w2] = COMPOSE_HAARiH0(b[x+w2], temp[x]);
113  }
114 
115  interleave(b, temp, temp+w2, w2, shift, shift);
116 }
117 
119 {
120  horizontal_compose_haari(b, temp, w, 0);
121 }
122 
124 {
125  horizontal_compose_haari(b, temp, w, 1);
126 }
127 
129 {
130  const int w2 = w >> 1;
131  int i, x;
132  IDWTELEM v[8];
133 
134  for (x = 0; x < w2; x++) {
135  for (i = 0; i < 8; i++)
136  v[i] = b[av_clip(x-3+i, 0, w2-1)];
137  tmp[x] = COMPOSE_FIDELITYiH0(v[0], v[1], v[2], v[3], b[x+w2], v[4], v[5], v[6], v[7]);
138  }
139 
140  for (x = 0; x < w2; x++) {
141  for (i = 0; i < 8; i++)
142  v[i] = tmp[av_clip(x-4+i, 0, w2-1)];
143  tmp[x+w2] = COMPOSE_FIDELITYiL0(v[0], v[1], v[2], v[3], b[x], v[4], v[5], v[6], v[7]);
144  }
145 
146  interleave(b, tmp+w2, tmp, w2, 0, 0);
147 }
148 
150 {
151  const int w2 = w >> 1;
152  int x, b0, b1, b2;
153 
154  temp[0] = COMPOSE_DAUB97iL1(b[w2], b[0], b[w2]);
155  for (x = 1; x < w2; x++) {
156  temp[x ] = COMPOSE_DAUB97iL1(b[x+w2-1], b[x ], b[x+w2]);
157  temp[x+w2-1] = COMPOSE_DAUB97iH1(temp[x-1], b[x+w2-1], temp[x]);
158  }
159  temp[w-1] = COMPOSE_DAUB97iH1(temp[w2-1], b[w-1], temp[w2-1]);
160 
161  // second stage combined with interleave and shift
162  b0 = b2 = COMPOSE_DAUB97iL0(temp[w2], temp[0], temp[w2]);
163  b[0] = (b0 + 1) >> 1;
164  for (x = 1; x < w2; x++) {
165  b2 = COMPOSE_DAUB97iL0(temp[x+w2-1], temp[x ], temp[x+w2]);
166  b1 = COMPOSE_DAUB97iH0( b0, temp[x+w2-1], b2 );
167  b[2*x-1] = (b1 + 1) >> 1;
168  b[2*x ] = (b2 + 1) >> 1;
169  b0 = b2;
170  }
171  b[w-1] = (COMPOSE_DAUB97iH0(b2, temp[w-1], b2) + 1) >> 1;
172 }
173 
175 {
176  int i;
177 
178  for(i=0; i<width; i++){
179  b1[i] = COMPOSE_DIRAC53iH0(b0[i], b1[i], b2[i]);
180  }
181 }
182 
184  IDWTELEM *b3, IDWTELEM *b4, int width)
185 {
186  int i;
187 
188  for(i=0; i<width; i++){
189  b2[i] = COMPOSE_DD97iH0(b0[i], b1[i], b2[i], b3[i], b4[i]);
190  }
191 }
192 
194  IDWTELEM *b3, IDWTELEM *b4, int width)
195 {
196  int i;
197 
198  for(i=0; i<width; i++){
199  b2[i] = COMPOSE_DD137iL0(b0[i], b1[i], b2[i], b3[i], b4[i]);
200  }
201 }
202 
203 static void vertical_compose_haar(IDWTELEM *b0, IDWTELEM *b1, int width)
204 {
205  int i;
206 
207  for (i = 0; i < width; i++) {
208  b0[i] = COMPOSE_HAARiL0(b0[i], b1[i]);
209  b1[i] = COMPOSE_HAARiH0(b1[i], b0[i]);
210  }
211 }
212 
214 {
215  int i;
216 
217  for(i=0; i<width; i++){
218  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]);
219  }
220 }
221 
223 {
224  int i;
225 
226  for(i=0; i<width; i++){
227  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]);
228  }
229 }
230 
232 {
233  int i;
234 
235  for(i=0; i<width; i++){
236  b1[i] = COMPOSE_DAUB97iH0(b0[i], b1[i], b2[i]);
237  }
238 }
239 
241 {
242  int i;
243 
244  for(i=0; i<width; i++){
245  b1[i] = COMPOSE_DAUB97iH1(b0[i], b1[i], b2[i]);
246  }
247 }
248 
250 {
251  int i;
252 
253  for(i=0; i<width; i++){
254  b1[i] = COMPOSE_DAUB97iL0(b0[i], b1[i], b2[i]);
255  }
256 }
257 
259 {
260  int i;
261 
262  for(i=0; i<width; i++){
263  b1[i] = COMPOSE_DAUB97iL1(b0[i], b1[i], b2[i]);
264  }
265 }
266 
267 
268 static void spatial_compose_dd97i_dy(DWTContext *d, int level, int width, int height, int stride)
269 {
270  vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
271  vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
272  DWTCompose *cs = d->cs + level;
273 
274  int i, y = cs->y;
275  IDWTELEM *b[8];
276  for (i = 0; i < 6; i++)
277  b[i] = cs->b[i];
278  b[6] = d->buffer + av_clip(y+5, 0, height-2)*stride;
279  b[7] = d->buffer + av_clip(y+6, 1, height-1)*stride;
280 
281  if(y+5<(unsigned)height) vertical_compose_l0( b[5], b[6], b[7], width);
282  if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
283 
284  if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
285  if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
286 
287  for (i = 0; i < 6; i++)
288  cs->b[i] = b[i+2];
289  cs->y += 2;
290 }
291 
292 static void spatial_compose_dirac53i_dy(DWTContext *d, int level, int width, int height, int stride)
293 {
294  vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
295  vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
296  DWTCompose *cs = d->cs + level;
297 
298  int y= cs->y;
299  IDWTELEM *b[4] = { cs->b[0], cs->b[1] };
300  b[2] = d->buffer + avpriv_mirror(y+1, height-1)*stride;
301  b[3] = d->buffer + avpriv_mirror(y+2, height-1)*stride;
302 
303  if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
304  if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
305 
306  if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
307  if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
308 
309  cs->b[0] = b[2];
310  cs->b[1] = b[3];
311  cs->y += 2;
312 }
313 
314 
315 static void spatial_compose_dd137i_dy(DWTContext *d, int level, int width, int height, int stride)
316 {
317  vertical_compose_5tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
318  vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
319  DWTCompose *cs = d->cs + level;
320 
321  int i, y = cs->y;
322  IDWTELEM *b[10];
323  for (i = 0; i < 8; i++)
324  b[i] = cs->b[i];
325  b[8] = d->buffer + av_clip(y+7, 0, height-2)*stride;
326  b[9] = d->buffer + av_clip(y+8, 1, height-1)*stride;
327 
328  if(y+5<(unsigned)height) vertical_compose_l0(b[3], b[5], b[6], b[7], b[9], width);
329  if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
330 
331  if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
332  if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
333 
334  for (i = 0; i < 8; i++)
335  cs->b[i] = b[i+2];
336  cs->y += 2;
337 }
338 
339 // haar makes the assumption that height is even (always true for dirac)
340 static void spatial_compose_haari_dy(DWTContext *d, int level, int width, int height, int stride)
341 {
342  vertical_compose_2tap vertical_compose = (void*)d->vertical_compose;
343  int y = d->cs[level].y;
344  IDWTELEM *b0 = d->buffer + (y-1)*stride;
345  IDWTELEM *b1 = d->buffer + (y )*stride;
346 
347  vertical_compose(b0, b1, width);
348  d->horizontal_compose(b0, d->temp, width);
349  d->horizontal_compose(b1, d->temp, width);
350 
351  d->cs[level].y += 2;
352 }
353 
354 // Don't do sliced idwt for fidelity; the 9 tap filter makes it a bit annoying
355 // Fortunately, this filter isn't used in practice.
356 static void spatial_compose_fidelity(DWTContext *d, int level, int width, int height, int stride)
357 {
358  vertical_compose_9tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
359  vertical_compose_9tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
360  int i, y;
361  IDWTELEM *b[8];
362 
363  for (y = 1; y < height; y += 2) {
364  for (i = 0; i < 8; i++)
365  b[i] = d->buffer + av_clip((y-7 + 2*i), 0, height-2)*stride;
366  vertical_compose_h0(d->buffer + y*stride, b, width);
367  }
368 
369  for (y = 0; y < height; y += 2) {
370  for (i = 0; i < 8; i++)
371  b[i] = d->buffer + av_clip((y-7 + 2*i), 1, height-1)*stride;
372  vertical_compose_l0(d->buffer + y*stride, b, width);
373  }
374 
375  for (y = 0; y < height; y++)
376  d->horizontal_compose(d->buffer + y*stride, d->temp, width);
377 
378  d->cs[level].y = height+1;
379 }
380 
381 static void spatial_compose_daub97i_dy(DWTContext *d, int level, int width, int height, int stride)
382 {
383  vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
384  vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
385  vertical_compose_3tap vertical_compose_l1 = (void*)d->vertical_compose_l1;
386  vertical_compose_3tap vertical_compose_h1 = (void*)d->vertical_compose_h1;
387  DWTCompose *cs = d->cs + level;
388 
389  int i, y = cs->y;
390  IDWTELEM *b[6];
391  for (i = 0; i < 4; i++)
392  b[i] = cs->b[i];
393  b[4] = d->buffer + avpriv_mirror(y+3, height-1)*stride;
394  b[5] = d->buffer + avpriv_mirror(y+4, height-1)*stride;
395 
396  if(y+3<(unsigned)height) vertical_compose_l1(b[3], b[4], b[5], width);
397  if(y+2<(unsigned)height) vertical_compose_h1(b[2], b[3], b[4], width);
398  if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
399  if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
400 
401  if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
402  if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
403 
404  for (i = 0; i < 4; i++)
405  cs->b[i] = b[i+2];
406  cs->y += 2;
407 }
408 
409 
411 {
412  cs->b[0] = buffer + avpriv_mirror(-3-1, height-1)*stride;
413  cs->b[1] = buffer + avpriv_mirror(-3 , height-1)*stride;
414  cs->b[2] = buffer + avpriv_mirror(-3+1, height-1)*stride;
415  cs->b[3] = buffer + avpriv_mirror(-3+2, height-1)*stride;
416  cs->y = -3;
417 }
418 
420 {
421  cs->b[0] = buffer + avpriv_mirror(-1-1, height-1)*stride;
422  cs->b[1] = buffer + avpriv_mirror(-1 , height-1)*stride;
423  cs->y = -1;
424 }
425 
427 {
428  cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
429  cs->b[1] = buffer + av_clip(-5 , 1, height-1)*stride;
430  cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
431  cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
432  cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
433  cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
434  cs->y = -5;
435 }
436 
438 {
439  cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
440  cs->b[1] = buffer + av_clip(-5 , 1, height-1)*stride;
441  cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
442  cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
443  cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
444  cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
445  cs->b[6] = buffer + av_clip(-5+5, 0, height-2)*stride;
446  cs->b[7] = buffer + av_clip(-5+6, 1, height-1)*stride;
447  cs->y = -5;
448 }
449 
451  int stride, enum dwt_type type, int decomposition_count,
452  IDWTELEM *temp)
453 {
454  int level;
455 
456  d->buffer = buffer;
457  d->width = width;
458  d->height = height;
459  d->stride = stride;
460  d->decomposition_count = decomposition_count;
461  d->temp = temp + 8;
462 
463  for(level=decomposition_count-1; level>=0; level--){
464  int hl = height >> level;
465  int stride_l = stride << level;
466 
467  switch(type){
468  case DWT_DIRAC_DD9_7:
469  spatial_compose_dd97i_init(d->cs+level, buffer, hl, stride_l);
470  break;
471  case DWT_DIRAC_LEGALL5_3:
472  spatial_compose53i_init2(d->cs+level, buffer, hl, stride_l);
473  break;
474  case DWT_DIRAC_DD13_7:
475  spatial_compose_dd137i_init(d->cs+level, buffer, hl, stride_l);
476  break;
477  case DWT_DIRAC_HAAR0:
478  case DWT_DIRAC_HAAR1:
479  d->cs[level].y = 1;
480  break;
481  case DWT_DIRAC_DAUB9_7:
482  spatial_compose97i_init2(d->cs+level, buffer, hl, stride_l);
483  break;
484  default:
485  d->cs[level].y = 0;
486  break;
487  }
488  }
489 
490  switch (type) {
491  case DWT_DIRAC_DD9_7:
496  d->support = 7;
497  break;
498  case DWT_DIRAC_LEGALL5_3:
503  d->support = 3;
504  break;
505  case DWT_DIRAC_DD13_7:
510  d->support = 7;
511  break;
512  case DWT_DIRAC_HAAR0:
513  case DWT_DIRAC_HAAR1:
516  if (type == DWT_DIRAC_HAAR0)
518  else
520  d->support = 1;
521  break;
522  case DWT_DIRAC_FIDELITY:
527  d->support = 0; // not really used
528  break;
529  case DWT_DIRAC_DAUB9_7:
536  d->support = 5;
537  break;
538  default:
539  av_log(NULL, AV_LOG_ERROR, "Unknown wavelet type %d\n", type);
540  return -1;
541  }
542 
543  if (HAVE_MMX) ff_spatial_idwt_init_mmx(d, type);
544 
545  return 0;
546 }
547 
549 {
550  int level, support = d->support;
551 
552  for (level = d->decomposition_count-1; level >= 0; level--) {
553  int wl = d->width >> level;
554  int hl = d->height >> level;
555  int stride_l = d->stride << level;
556 
557  while (d->cs[level].y <= FFMIN((y>>level)+support, hl))
558  d->spatial_compose(d, level, wl, hl, stride_l);
559  }
560 }
561