Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * libng filter -- Smooth the image to reduce snow at bad TV receiption
  3  *
  4  *
  5  * Filter options
  6  * --------------
  7  *
  8  * There are 2 options available that can be turned on and off separately.
  9  *
 10  * Smooth over time:    Calculate average of previous and current frame.
 11  *                      Longer filter lengths could improve static
 12  *                      images but would be unusable for movies and
 13  *                      require high CPU power. I found averaging of
 14  *                      2 frames the most useful filter.
 15  *
 16  * Smooth horizontally: For every pixel, the average of the actual colour
 17  *                      and the colour of the pixel to the left is displayed.
 18  *
 19  *
 20  * (c) 2002  Klaus Peichl <pei@freenet.de> (smoothing filter),
 21  *           Gerd Knorr <kraxel@bytesex.org> (framework)
 22  *
 23  */
 24 
 25 #include "config.h"
 26 
 27 #include <stdio.h>
 28 #include <stdlib.h>
 29 #include <pthread.h>
 30 
 31 #include "grab-ng.h"
 32 
 33 /* ------------------------------------------------------------------- */
 34 
 35 typedef struct {
 36   struct ng_video_buf * pLastFrame;
 37 }
 38 SMOOTH_BUFFER;
 39 
 40 
 41 static int smoothTime = 1;
 42 static int smoothHorizontal = 1;
 43 
 44 
 45 static void inline
 46 invert_bytes(unsigned char *dst, unsigned char *src, int bytes)
 47 {
 48     while (bytes--)
 49         *(dst++) = 0xff - *(src++);
 50 }
 51 
 52 
 53 #if 1
 54 
 55 /*
 56   Fast 32-bit smoothing
 57 */
 58 static void inline
 59 smooth_native_32bit(unsigned int *last,
 60                     unsigned int *dst,
 61                     unsigned int *src,
 62                     int pixels)
 63 {
 64   unsigned int  old,new, old2,new2;
 65 
 66   if (smoothTime && smoothHorizontal) {
 67 
 68     /* Smoothing in time and horizontally */
 69 
 70     old2 = *last;
 71     new2 = *src;
 72 
 73     while (pixels--) {
 74 
 75       old = *last;
 76       new = *src++;
 77       *last++ = new;
 78 
 79       /*
 80         Fast averaging:
 81         All 4 bytes (of which only 3 are used) can be averaged in one 32bit-word.
 82         The lowest 2 bits of every colour are thrown away to avoid influences
 83         between the colours.
 84       */
 85 
 86       *dst++ =
 87         ((new >> 2) & 0x3F3F3F3F) +
 88         ((new2 >> 2) & 0x3F3F3F3F) +
 89         ((old >> 2) & 0x3F3F3F3F) +
 90         ((old2 >> 2) & 0x3F3F3F3F);
 91 
 92       old2 = old;
 93       new2 = new;
 94     }
 95   }
 96   else if (smoothTime) {
 97 
 98     /* Smoothing in time only */
 99 
100     while (pixels--) {
101 
102       old = *last;
103       new = *src++;
104       *last++ = new;
105 
106       /*
107         Fast averaging:
108         All 4 bytes (of which only 3 are used) can be averaged in one 32bit-word.
109         The lowest bit of every colour is thrown away to avoid influences
110         between the colours.
111       */
112 
113       *dst++ =
114         ((new >> 1) & 0x7F7F7F7F) +
115         ((old >> 1) & 0x7F7F7F7F);
116     }
117   }
118   else if (smoothHorizontal) {
119 
120     /* Smooth horizontally only */
121 
122     new2 = *src;
123 
124     while (pixels--) {
125 
126       new = *src++;
127       *last++ = new;
128 
129       /*
130         Fast averaging:
131         All 4 bytes (of which only 3 are used) can be averaged in one 32bit-word.
132         The lowest bit of every colour is thrown away to avoid influences
133         between the colours.
134       */
135 
136       *dst++ =
137         ((new >> 1) & 0x7F7F7F7F) +
138         ((new2 >> 1) & 0x7F7F7F7F);
139 
140       new2 = new;
141     }
142   }
143   else {
144 
145     /* No smoothing at all */
146 
147     while (pixels--) {
148       new = *src++;
149       *last++ = new;
150       *dst++ = new;
151     }
152   }
153 }
154 
155 #else
156 
157 /*
158   This is an alternative implementation of the above function
159   which does not throw away the lowest bits before addition.
160   It is derived from the byte-based 24-bit-function below but
161   processes 4 bytes for every pixel instead of 3.
162 */
163 
164 static void inline
165 smooth_native_32bit(unsigned char *last,
166                     unsigned char *dst,
167                     unsigned char *src,
168                     int pixels)
169 {
170   unsigned char  oldR,newR, oldR2,newR2;
171   unsigned char  oldG,newG, oldG2,newG2;
172   unsigned char  oldB,newB, oldB2,newB2;
173   unsigned char  oldP,newP, oldP2,newP2;
174 
175   if (smoothTime && smoothHorizontal) {
176 
177     /* Smoothing in time and horizontally */
178 
179     oldR2 = last[0];
180     oldG2 = last[1];
181     oldB2 = last[2];
182     oldP2 = last[3];
183     newR2 = src[0];
184     newG2 = src[1];
185     newB2 = src[2];
186     newP2 = src[3];
187 
188     while (pixels--) {
189 
190       oldR = *last;  newR = *src++;  *last++ = newR;
191       oldG = *last;  newG = *src++;  *last++ = newG;
192       oldB = *last;  newB = *src++;  *last++ = newB;
193       oldP = *last;  newP = *src++;  *last++ = newP;
194 
195       *dst++ = (newR + oldR + newR2 + oldR2) / 4;
196       *dst++ = (newG + oldG + newG2 + oldG2) / 4;
197       *dst++ = (newB + oldB + newB2 + oldB2) / 4;
198       *dst++ = (newP + oldP + newP2 + oldP2) / 4;
199 
200       oldR2 = oldR;
201       oldG2 = oldG;
202       oldB2 = oldB;
203       oldP2 = oldP;
204 
205       newR2 = newR;
206       newG2 = newG;
207       newB2 = newB;
208       newP2 = newP;
209     }
210   }
211   else if (smoothTime) {
212 
213     /* Smoothing in time only */
214 
215     while (pixels--) {
216 
217       oldR = *last;  newR = *src++;  *last++ = newR;
218       oldG = *last;  newG = *src++;  *last++ = newG;
219       oldB = *last;  newB = *src++;  *last++ = newB;
220       oldP = *last;  newP = *src++;  *last++ = newP;
221 
222       *dst++ = (newR + oldR) / 2;
223       *dst++ = (newG + oldG) / 2;
224       *dst++ = (newB + oldB) / 2;
225       *dst++ = (newP + oldP) / 2;
226     }
227   }
228   else if (smoothHorizontal) {
229 
230     /* Smooth horizontally only */
231 
232     newR2 = src[0];
233     newG2 = src[1];
234     newB2 = src[2];
235     newP2 = src[3];
236 
237     while (pixels--) {
238 
239       newR = *src++;  *last++ = newR;
240       newG = *src++;  *last++ = newG;
241       newB = *src++;  *last++ = newB;
242       newP = *src++;  *last++ = newP;
243 
244       *dst++ = (newR + newR2) / 2;
245       *dst++ = (newG + newG2) / 2;
246       *dst++ = (newB + newB2) / 2;
247       *dst++ = (newP + newP2) / 2;
248 
249       newR2 = newR;
250       newG2 = newG;
251       newB2 = newB;
252       newP2 = newP;
253     }
254   }
255   else {
256 
257     /* No smoothing at all */
258 
259     while (pixels--) {
260       newR = *src++;  *last++ = newR;  *dst++ = newR;
261       newG = *src++;  *last++ = newG;  *dst++ = newG;
262       newB = *src++;  *last++ = newB;  *dst++ = newB;
263       newP = *src++;  *last++ = newP;  *dst++ = newP;
264 
265     }
266   }
267 }
268 #endif
269 
270 
271 static void inline
272 smooth_native_24bit(unsigned char *last,
273                     unsigned char *dst,
274                     unsigned char *src,
275                     int pixels)
276 {
277   unsigned char  oldR,newR, oldR2,newR2;
278   unsigned char  oldG,newG, oldG2,newG2;
279   unsigned char  oldB,newB, oldB2,newB2;
280 
281   if (smoothTime && smoothHorizontal) {
282 
283     /* Smoothing in time and horizontally */
284 
285     oldR2 = last[0];
286     oldG2 = last[1];
287     oldB2 = last[2];
288     newR2 = src[0];
289     newG2 = src[1];
290     newB2 = src[2];
291 
292     while (pixels--) {
293 
294       oldR = *last;  newR = *src++;  *last++ = newR;
295       oldG = *last;  newG = *src++;  *last++ = newG;
296       oldB = *last;  newB = *src++;  *last++ = newB;
297 
298       *dst++ = (newR + oldR + newR2 + oldR2) / 4;
299       *dst++ = (newG + oldG + newG2 + oldG2) / 4;
300       *dst++ = (newB + oldB + newB2 + oldB2) / 4;
301 
302       oldR2 = oldR;
303       oldG2 = oldG;
304       oldB2 = oldB;
305 
306       newR2 = newR;
307       newG2 = newG;
308       newB2 = newB;
309     }
310   }
311   else if (smoothTime) {
312 
313     /* Smoothing in time only */
314 
315     while (pixels--) {
316 
317       oldR = *last;  newR = *src++;  *last++ = newR;
318       oldG = *last;  newG = *src++;  *last++ = newG;
319       oldB = *last;  newB = *src++;  *last++ = newB;
320 
321       *dst++ = (newR + oldR) / 2;
322       *dst++ = (newG + oldG) / 2;
323       *dst++ = (newB + oldB) / 2;
324     }
325   }
326   else if (smoothHorizontal) {
327 
328     /* Smooth horizontally only */
329 
330     newR2 = src[0];
331     newG2 = src[1];
332     newB2 = src[2];
333 
334     while (pixels--) {
335 
336       newR = *src++;  *last++ = newR;
337       newG = *src++;  *last++ = newG;
338       newB = *src++;  *last++ = newB;
339 
340       *dst++ = (newR + newR2) / 2;
341       *dst++ = (newG + newG2) / 2;
342       *dst++ = (newB + newB2) / 2;
343 
344       newR2 = newR;
345       newG2 = newG;
346       newB2 = newB;
347     }
348   }
349   else {
350 
351     /* No smoothing at all */
352 
353     while (pixels--) {
354       newR = *src++;  *last++ = newR;  *dst++ = newR;
355       newG = *src++;  *last++ = newG;  *dst++ = newG;
356       newB = *src++;  *last++ = newB;  *dst++ = newB;
357 
358     }
359   }
360 }
361 
362 
363 static void inline
364 smooth_native_16bit(unsigned short *last,
365                     unsigned short *dst,
366                     unsigned short *src,
367                     unsigned short maskR,
368                     unsigned short maskG,
369                     unsigned short maskB,
370                     int pixels)
371 {
372   unsigned short  old,new, old2,new2;
373   unsigned short  red,green,blue;
374 
375   if (smoothTime && smoothHorizontal) {
376 
377     /* Smoothing in time and horizontally */
378 
379     old2 = *last;
380     new2 = *src;
381 
382     while (pixels--) {
383 
384       old = *last;
385       new = *src++;
386       *last++ = new;
387 
388       red   = ( ((new & maskR) + (old & maskR) + (new2 & maskR) + (old2 & maskR))/4 ) & maskR;
389       green = ( ((new & maskG) + (old & maskG) + (new2 & maskG) + (old2 & maskG))/4 ) & maskG;
390       blue  = ( ((new & maskB) + (old & maskB) + (new2 & maskB) + (old2 & maskB))/4 ) & maskB;
391       *dst++ = red | green | blue;
392 
393       old2 = old;
394       new2 = new;
395     }
396   }
397   else if (smoothTime) {
398 
399     /* Smoothing in time only */
400 
401     while (pixels--) {
402 
403       old = *last;
404       new = *src++;
405       *last++ = new;
406 
407       red   = ( ((new & maskR) + (old & maskR))/2 ) & maskR;
408       green = ( ((new & maskG) + (old & maskG))/2 ) & maskG;
409       blue  = ( ((new & maskB) + (old & maskB))/2 ) & maskB;
410       *dst++ = red | green | blue;
411     }
412   }
413   else if (smoothHorizontal) {
414 
415     /* Smooth horizontally only */
416 
417     new2 = *src;
418 
419     while (pixels--) {
420 
421       new = *src++;
422       *last++ = new;
423 
424       red   = ( ((new & maskR) + (new2 & maskR))/2 ) & maskR;
425       green = ( ((new & maskG) + (new2 & maskG))/2 ) & maskG;
426       blue  = ( ((new & maskB) + (new2 & maskB))/2 ) & maskB;
427       *dst++ = red | green | blue;
428 
429       new2 = new;
430     }
431   }
432   else {
433 
434     /* No smoothing at all */
435 
436     while (pixels--) {
437       new = *src++;
438       *last++ = new;
439       *dst++ = new;
440     }
441   }
442 }
443 
444 
445 /* ------------------------------------------------------------------- */
446 
447 static void *init(struct ng_video_fmt *out)
448 {
449     /* don't have to carry around status info */
450     static SMOOTH_BUFFER smooth_buffer;
451 
452     smooth_buffer.pLastFrame = ng_malloc_video_buf(out, out->height * out->bytesperline);
453 
454     return &smooth_buffer;
455 }
456 
457 static struct ng_video_buf*
458 frame(void *h, struct ng_video_buf *in)
459 {
460     SMOOTH_BUFFER *handle = h;
461     struct ng_video_buf *out;
462     unsigned char *dst;
463     unsigned char *src;
464     unsigned char *last;
465     unsigned int y,cnt;
466 
467     out = ng_malloc_video_buf(&in->fmt, in->fmt.height * in->fmt.bytesperline);
468     out->info = in->info;
469 
470     dst = out->data;
471     src = in->data;
472     last = handle->pLastFrame->data;
473     cnt = in->fmt.width * ng_vfmt_to_depth[in->fmt.fmtid] / 8;
474 
475     for (y = 0; y < in->fmt.height; y++) {
476         switch (in->fmt.fmtid) {
477         case VIDEO_GRAY:
478         case VIDEO_BGR24:
479         case VIDEO_RGB24:
480             smooth_native_24bit((unsigned char*)last,
481                                 (unsigned char*)dst,
482                                 (unsigned char*)src,
483                                 in->fmt.width);
484             break;
485         case VIDEO_BGR32:
486         case VIDEO_RGB32:
487         case VIDEO_YUYV:
488         case VIDEO_UYVY:
489             smooth_native_32bit((unsigned int*)last,
490                                 (unsigned int*)dst,
491                                 (unsigned int*)src,
492                                 in->fmt.width);
493             break;
494         case VIDEO_RGB15_NATIVE:
495             smooth_native_16bit((unsigned short*)last,
496                                 (unsigned short*)dst,
497                                 (unsigned short*)src,
498                                 0x7C00,  /* mask for red */
499                                 0x03E0,  /* mask for green */
500                                 0x001F,  /* mask for blue */
501                                 in->fmt.width);
502             break;
503         case VIDEO_RGB16_NATIVE:
504             smooth_native_16bit((unsigned short*)last,
505                                 (unsigned short*)dst,
506                                 (unsigned short*)src,
507                                 0xF800,  /* mask for red */
508                                 0x07E0,  /* mask for green */
509                                 0x001F,  /* mask for blue */
510                                 in->fmt.width);
511             break;
512         }
513         dst += out->fmt.bytesperline;
514         src += in->fmt.bytesperline;
515         last += in->fmt.bytesperline;
516     }
517 
518     ng_release_video_buf(in);
519     return out;
520 }
521 
522 static void fini(void *handle)
523 {
524   ng_release_video_buf(handle);
525 }
526 
527 
528 static int read_attr(struct ng_attribute *attr)
529 {
530   int value;
531 
532   switch (attr->id) {
533   case 0:
534     value = smoothTime;
535     break;
536   case 1:
537     value = smoothHorizontal;
538     break;
539   default:
540     value = 0;
541   }
542 
543   return value;
544 }
545 
546 static void write_attr(struct ng_attribute *attr, int value)
547 {
548   switch (attr->id) {
549   case 0:
550     smoothTime = value;
551     break;
552   case 1:
553     smoothHorizontal = value;
554     break;
555   }
556 }
557 
558 
559 /* ------------------------------------------------------------------- */
560 
561 static struct ng_attribute attrs[] = {
562     {
563         id:       0,
564         name:     "smooth over time",
565         type:     ATTR_TYPE_BOOL,
566         defval:   1,
567         read:     read_attr,
568         write:    write_attr,
569     },{
570         id:       1,
571         name:     "smooth horizontally",
572         type:     ATTR_TYPE_BOOL,
573         defval:   1,
574         read:     read_attr,
575         write:    write_attr,
576     },{
577         /* end of list */
578     }
579 };
580 
581 
582 static struct ng_filter filter = {
583     name:    "smooth",
584     attrs:   attrs,
585     fmts:
586     (1 << VIDEO_GRAY)         |
587     (1 << VIDEO_RGB15_NATIVE) |
588     (1 << VIDEO_RGB16_NATIVE) |
589     (1 << VIDEO_BGR24)        |
590     (1 << VIDEO_RGB24)        |
591     (1 << VIDEO_BGR32)        |
592     (1 << VIDEO_RGB32)        |
593     (1 << VIDEO_YUYV)         |
594     (1 << VIDEO_UYVY),
595     init:    init,
596     frame:   frame,
597     fini:    fini,
598 };
599 
600 extern void ng_plugin_init(void);
601 void ng_plugin_init(void)
602 {
603     ng_filter_register(NG_PLUGIN_MAGIC,__FILE__,&filter);
604 }
605 
  This page was automatically generated by the LXR engine.