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 inline int mirror(int v, int m)
30 {
31  while ((unsigned)v > (unsigned)m) {
32  v = -v;
33  if (v < 0)
34  v += 2 * m;
35  }
36  return v;
37 }
38 
39 static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
40  int width)
41 {
42  int i;
43 
44  for (i = 0; i < width; i++)
45  b1[i] -= (b0[i] + b2[i] + 2) >> 2;
46 }
47 
48 
49 static av_always_inline
50 void interleave(IDWTELEM *dst, IDWTELEM *src0, IDWTELEM *src1, int w2, int add, int shift)
51 {
52  int i;
53  for (i = 0; i < w2; i++) {
54  dst[2*i ] = (src0[i] + add) >> shift;
55  dst[2*i+1] = (src1[i] + add) >> shift;
56  }
57 }
58 
60 {
61  const int w2 = w >> 1;
62  int x;
63 
64  temp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
65  for (x = 1; x < w2; x++) {
66  temp[x ] = COMPOSE_53iL0 (b[x+w2-1], b[x ], b[x+w2]);
67  temp[x+w2-1] = COMPOSE_DIRAC53iH0(temp[x-1], b[x+w2-1], temp[x]);
68  }
69  temp[w-1] = COMPOSE_DIRAC53iH0(temp[w2-1], b[w-1], temp[w2-1]);
70 
71  interleave(b, temp, temp+w2, w2, 1, 1);
72 }
73 
74 static void horizontal_compose_dd97i(IDWTELEM *b, IDWTELEM *tmp, int w)
75 {
76  const int w2 = w >> 1;
77  int x;
78 
79  tmp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
80  for (x = 1; x < w2; x++)
81  tmp[x] = COMPOSE_53iL0(b[x+w2-1], b[x], b[x+w2]);
82 
83  // extend the edges
84  tmp[-1] = tmp[0];
85  tmp[w2+1] = tmp[w2] = tmp[w2-1];
86 
87  for (x = 0; x < w2; x++) {
88  b[2*x ] = (tmp[x] + 1)>>1;
89  b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
90  }
91 }
92 
93 static void horizontal_compose_dd137i(IDWTELEM *b, IDWTELEM *tmp, int w)
94 {
95  const int w2 = w >> 1;
96  int x;
97 
98  tmp[0] = COMPOSE_DD137iL0(b[w2], b[w2], b[0], b[w2 ], b[w2+1]);
99  tmp[1] = COMPOSE_DD137iL0(b[w2], b[w2], b[1], b[w2+1], b[w2+2]);
100  for (x = 2; x < w2-1; x++)
101  tmp[x] = COMPOSE_DD137iL0(b[x+w2-2], b[x+w2-1], b[x], b[x+w2], b[x+w2+1]);
102  tmp[w2-1] = COMPOSE_DD137iL0(b[w-3], b[w-2], b[w2-1], b[w-1], b[w-1]);
103 
104  // extend the edges
105  tmp[-1] = tmp[0];
106  tmp[w2+1] = tmp[w2] = tmp[w2-1];
107 
108  for (x = 0; x < w2; x++) {
109  b[2*x ] = (tmp[x] + 1)>>1;
110  b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
111  }
112 }
113 
114 static av_always_inline
116 {
117  const int w2 = w >> 1;
118  int x;
119 
120  for (x = 0; x < w2; x++) {
121  temp[x ] = COMPOSE_HAARiL0(b[x ], b[x+w2]);
122  temp[x+w2] = COMPOSE_HAARiH0(b[x+w2], temp[x]);
123  }
124 
125  interleave(b, temp, temp+w2, w2, shift, shift);
126 }
127 
129 {
130  horizontal_compose_haari(b, temp, w, 0);
131 }
132 
134 {
135  horizontal_compose_haari(b, temp, w, 1);
136 }
137 
139 {
140  const int w2 = w >> 1;
141  int i, x;
142  IDWTELEM v[8];
143 
144  for (x = 0; x < w2; x++) {
145  for (i = 0; i < 8; i++)
146  v[i] = b[av_clip(x-3+i, 0, w2-1)];
147  tmp[x] = COMPOSE_FIDELITYiH0(v[0], v[1], v[2], v[3], b[x+w2], v[4], v[5], v[6], v[7]);
148  }
149 
150  for (x = 0; x < w2; x++) {
151  for (i = 0; i < 8; i++)
152  v[i] = tmp[av_clip(x-4+i, 0, w2-1)];
153  tmp[x+w2] = COMPOSE_FIDELITYiL0(v[0], v[1], v[2], v[3], b[x], v[4], v[5], v[6], v[7]);
154  }
155 
156  interleave(b, tmp+w2, tmp, w2, 0, 0);
157 }
158 
160 {
161  const int w2 = w >> 1;
162  int x, b0, b1, b2;
163 
164  temp[0] = COMPOSE_DAUB97iL1(b[w2], b[0], b[w2]);
165  for (x = 1; x < w2; x++) {
166  temp[x ] = COMPOSE_DAUB97iL1(b[x+w2-1], b[x ], b[x+w2]);
167  temp[x+w2-1] = COMPOSE_DAUB97iH1(temp[x-1], b[x+w2-1], temp[x]);
168  }
169  temp[w-1] = COMPOSE_DAUB97iH1(temp[w2-1], b[w-1], temp[w2-1]);
170 
171  // second stage combined with interleave and shift
172  b0 = b2 = COMPOSE_DAUB97iL0(temp[w2], temp[0], temp[w2]);
173  b[0] = (b0 + 1) >> 1;
174  for (x = 1; x < w2; x++) {
175  b2 = COMPOSE_DAUB97iL0(temp[x+w2-1], temp[x ], temp[x+w2]);
176  b1 = COMPOSE_DAUB97iH0( b0, temp[x+w2-1], b2 );
177  b[2*x-1] = (b1 + 1) >> 1;
178  b[2*x ] = (b2 + 1) >> 1;
179  b0 = b2;
180  }
181  b[w-1] = (COMPOSE_DAUB97iH0(b2, temp[w-1], b2) + 1) >> 1;
182 }
183 
185 {
186  int i;
187 
188  for(i=0; i<width; i++){
189  b1[i] = COMPOSE_DIRAC53iH0(b0[i], b1[i], b2[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_DD97iH0(b0[i], b1[i], b2[i], b3[i], b4[i]);
200  }
201 }
202 
204  IDWTELEM *b3, IDWTELEM *b4, int width)
205 {
206  int i;
207 
208  for(i=0; i<width; i++){
209  b2[i] = COMPOSE_DD137iL0(b0[i], b1[i], b2[i], b3[i], b4[i]);
210  }
211 }
212 
213 static void vertical_compose_haar(IDWTELEM *b0, IDWTELEM *b1, int width)
214 {
215  int i;
216 
217  for (i = 0; i < width; i++) {
218  b0[i] = COMPOSE_HAARiL0(b0[i], b1[i]);
219  b1[i] = COMPOSE_HAARiH0(b1[i], b0[i]);
220  }
221 }
222 
224 {
225  int i;
226 
227  for(i=0; i<width; i++){
228  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]);
229  }
230 }
231 
233 {
234  int i;
235 
236  for(i=0; i<width; i++){
237  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]);
238  }
239 }
240 
242 {
243  int i;
244 
245  for(i=0; i<width; i++){
246  b1[i] = COMPOSE_DAUB97iH0(b0[i], b1[i], b2[i]);
247  }
248 }
249 
251 {
252  int i;
253 
254  for(i=0; i<width; i++){
255  b1[i] = COMPOSE_DAUB97iH1(b0[i], b1[i], b2[i]);
256  }
257 }
258 
260 {
261  int i;
262 
263  for(i=0; i<width; i++){
264  b1[i] = COMPOSE_DAUB97iL0(b0[i], b1[i], b2[i]);
265  }
266 }
267 
269 {
270  int i;
271 
272  for(i=0; i<width; i++){
273  b1[i] = COMPOSE_DAUB97iL1(b0[i], b1[i], b2[i]);
274  }
275 }
276 
277 
278 static void spatial_compose_dd97i_dy(DWTContext *d, int level, int width, int height, int stride)
279 {
280  vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
281  vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
282  DWTCompose *cs = d->cs + level;
283 
284  int i, y = cs->y;
285  IDWTELEM *b[8];
286  for (i = 0; i < 6; i++)
287  b[i] = cs->b[i];
288  b[6] = d->buffer + av_clip(y+5, 0, height-2)*stride;
289  b[7] = d->buffer + av_clip(y+6, 1, height-1)*stride;
290 
291  if(y+5<(unsigned)height) vertical_compose_l0( b[5], b[6], b[7], width);
292  if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
293 
294  if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
295  if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
296 
297  for (i = 0; i < 6; i++)
298  cs->b[i] = b[i+2];
299  cs->y += 2;
300 }
301 
302 static void spatial_compose_dirac53i_dy(DWTContext *d, int level, int width, int height, int stride)
303 {
304  vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
305  vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
306  DWTCompose *cs = d->cs + level;
307 
308  int y= cs->y;
309  IDWTELEM *b[4] = { cs->b[0], cs->b[1] };
310  b[2] = d->buffer + mirror(y+1, height-1)*stride;
311  b[3] = d->buffer + mirror(y+2, height-1)*stride;
312 
313  if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
314  if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
315 
316  if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
317  if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
318 
319  cs->b[0] = b[2];
320  cs->b[1] = b[3];
321  cs->y += 2;
322 }
323 
324 
325 static void spatial_compose_dd137i_dy(DWTContext *d, int level, int width, int height, int stride)
326 {
327  vertical_compose_5tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
328  vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
329  DWTCompose *cs = d->cs + level;
330 
331  int i, y = cs->y;
332  IDWTELEM *b[10];
333  for (i = 0; i < 8; i++)
334  b[i] = cs->b[i];
335  b[8] = d->buffer + av_clip(y+7, 0, height-2)*stride;
336  b[9] = d->buffer + av_clip(y+8, 1, height-1)*stride;
337 
338  if(y+5<(unsigned)height) vertical_compose_l0(b[3], b[5], b[6], b[7], b[9], width);
339  if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
340 
341  if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
342  if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
343 
344  for (i = 0; i < 8; i++)
345  cs->b[i] = b[i+2];
346  cs->y += 2;
347 }
348 
349 // haar makes the assumption that height is even (always true for dirac)
350 static void spatial_compose_haari_dy(DWTContext *d, int level, int width, int height, int stride)
351 {
352  vertical_compose_2tap vertical_compose = (void*)d->vertical_compose;
353  int y = d->cs[level].y;
354  IDWTELEM *b0 = d->buffer + (y-1)*stride;
355  IDWTELEM *b1 = d->buffer + (y )*stride;
356 
357  vertical_compose(b0, b1, width);
358  d->horizontal_compose(b0, d->temp, width);
359  d->horizontal_compose(b1, d->temp, width);
360 
361  d->cs[level].y += 2;
362 }
363 
364 // Don't do sliced idwt for fidelity; the 9 tap filter makes it a bit annoying
365 // Fortunately, this filter isn't used in practice.
366 static void spatial_compose_fidelity(DWTContext *d, int level, int width, int height, int stride)
367 {
368  vertical_compose_9tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
369  vertical_compose_9tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
370  int i, y;
371  IDWTELEM *b[8];
372 
373  for (y = 1; y < height; y += 2) {
374  for (i = 0; i < 8; i++)
375  b[i] = d->buffer + av_clip((y-7 + 2*i), 0, height-2)*stride;
376  vertical_compose_h0(d->buffer + y*stride, b, width);
377  }
378 
379  for (y = 0; y < height; y += 2) {
380  for (i = 0; i < 8; i++)
381  b[i] = d->buffer + av_clip((y-7 + 2*i), 1, height-1)*stride;
382  vertical_compose_l0(d->buffer + y*stride, b, width);
383  }
384 
385  for (y = 0; y < height; y++)
386  d->horizontal_compose(d->buffer + y*stride, d->temp, width);
387 
388  d->cs[level].y = height+1;
389 }
390 
391 static void spatial_compose_daub97i_dy(DWTContext *d, int level, int width, int height, int stride)
392 {
393  vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
394  vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
395  vertical_compose_3tap vertical_compose_l1 = (void*)d->vertical_compose_l1;
396  vertical_compose_3tap vertical_compose_h1 = (void*)d->vertical_compose_h1;
397  DWTCompose *cs = d->cs + level;
398 
399  int i, y = cs->y;
400  IDWTELEM *b[6];
401  for (i = 0; i < 4; i++)
402  b[i] = cs->b[i];
403  b[4] = d->buffer + mirror(y+3, height-1)*stride;
404  b[5] = d->buffer + mirror(y+4, height-1)*stride;
405 
406  if(y+3<(unsigned)height) vertical_compose_l1(b[3], b[4], b[5], width);
407  if(y+2<(unsigned)height) vertical_compose_h1(b[2], b[3], b[4], width);
408  if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
409  if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
410 
411  if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
412  if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
413 
414  for (i = 0; i < 4; i++)
415  cs->b[i] = b[i+2];
416  cs->y += 2;
417 }
418 
419 
421 {
422  cs->b[0] = buffer + mirror(-3-1, height-1)*stride;
423  cs->b[1] = buffer + mirror(-3 , height-1)*stride;
424  cs->b[2] = buffer + mirror(-3+1, height-1)*stride;
425  cs->b[3] = buffer + mirror(-3+2, height-1)*stride;
426  cs->y = -3;
427 }
428 
430 {
431  cs->b[0] = buffer + mirror(-1-1, height-1)*stride;
432  cs->b[1] = buffer + mirror(-1 , height-1)*stride;
433  cs->y = -1;
434 }
435 
437 {
438  cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
439  cs->b[1] = buffer + av_clip(-5 , 1, height-1)*stride;
440  cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
441  cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
442  cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
443  cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
444  cs->y = -5;
445 }
446 
448 {
449  cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
450  cs->b[1] = buffer + av_clip(-5 , 1, height-1)*stride;
451  cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
452  cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
453  cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
454  cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
455  cs->b[6] = buffer + av_clip(-5+5, 0, height-2)*stride;
456  cs->b[7] = buffer + av_clip(-5+6, 1, height-1)*stride;
457  cs->y = -5;
458 }
459 
461  int stride, enum dwt_type type, int decomposition_count,
462  IDWTELEM *temp)
463 {
464  int level;
465 
466  d->buffer = buffer;
467  d->width = width;
468  d->height = height;
469  d->stride = stride;
470  d->decomposition_count = decomposition_count;
471  d->temp = temp + 8;
472 
473  for(level=decomposition_count-1; level>=0; level--){
474  int hl = height >> level;
475  int stride_l = stride << level;
476 
477  switch(type){
478  case DWT_DIRAC_DD9_7:
479  spatial_compose_dd97i_init(d->cs+level, buffer, hl, stride_l);
480  break;
481  case DWT_DIRAC_LEGALL5_3:
482  spatial_compose53i_init2(d->cs+level, buffer, hl, stride_l);
483  break;
484  case DWT_DIRAC_DD13_7:
485  spatial_compose_dd137i_init(d->cs+level, buffer, hl, stride_l);
486  break;
487  case DWT_DIRAC_HAAR0:
488  case DWT_DIRAC_HAAR1:
489  d->cs[level].y = 1;
490  break;
491  case DWT_DIRAC_DAUB9_7:
492  spatial_compose97i_init2(d->cs+level, buffer, hl, stride_l);
493  break;
494  default:
495  d->cs[level].y = 0;
496  break;
497  }
498  }
499 
500  switch (type) {
501  case DWT_DIRAC_DD9_7:
506  d->support = 7;
507  break;
508  case DWT_DIRAC_LEGALL5_3:
513  d->support = 3;
514  break;
515  case DWT_DIRAC_DD13_7:
520  d->support = 7;
521  break;
522  case DWT_DIRAC_HAAR0:
523  case DWT_DIRAC_HAAR1:
526  if (type == DWT_DIRAC_HAAR0)
528  else
530  d->support = 1;
531  break;
532  case DWT_DIRAC_FIDELITY:
537  d->support = 0; // not really used
538  break;
539  case DWT_DIRAC_DAUB9_7:
546  d->support = 5;
547  break;
548  default:
549  av_log(NULL, AV_LOG_ERROR, "Unknown wavelet type %d\n", type);
550  return -1;
551  }
552 
553  if (HAVE_MMX) ff_spatial_idwt_init_mmx(d, type);
554 
555  return 0;
556 }
557 
559 {
560  int level, support = d->support;
561 
562  for (level = d->decomposition_count-1; level >= 0; level--) {
563  int wl = d->width >> level;
564  int hl = d->height >> level;
565  int stride_l = d->stride << level;
566 
567  while (d->cs[level].y <= FFMIN((y>>level)+support, hl))
568  d->spatial_compose(d, level, wl, hl, stride_l);
569  }
570 }
571