1 /*
2  * Simple xawtv deinterlacing plugin - cubic interpolation
3  *
4  * CAVEATS: Effectively halves framerate, (working on it)
5  * May cause some general slowness (uses more cpu) but the framerate is smooth
6  * on my athlon 700, running the -mjc branch of 2.4 kernel (preempt and other
7  * patches for desktop performance)
8  *
9  * BENEFITS: It's no longer interlaced ;)
10  * Looks a metric shitton better than line doubling & bilinear interpolation
11  * around text, but these nasty white specks occur on the border of pure black
12  * (0) and pure white (255).  My original theory was that it had something to
13  * do with 0 messing up our multiplication, but that does not appear to be the
14  * case based on preliminary fiddling around.
15  *
16  * AUTHORS:
17  * Conrad Kreyling <conrad@conrad.nerdland.org>
18  * Patrick Barrett <yebyen@nerdland.org>
19  *
20  * This is licenced under the GNU GPL until someone tells me I'm stealing code
21  * and can't do that ;) www.gnu.org for any version of the license.
22  *
23  * Based on xawtv-3.66/libng/plugins/flt-nop.c (also GPL)
24  * Cubic deinterlacing algorithm adapted from mplayer's libpostproc
25  */
26 
27 
28 #include "config.h"
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <pthread.h>
33 
34 #include "grab-ng.h"
35 
36 /*static int isOdd; // Global variable so we can tell if a frame uses even or
37 		  //odd scanlines, not implemented properly yet */
38 
39 static void inline
deinterlace(struct ng_video_buf * frame)40 deinterlace (struct ng_video_buf *frame)
41 {
42   unsigned int x, y, bytes = frame->fmt.bytesperline;
43 
44   /*
45    * if(isOdd){
46    *     isOdd=0;
47    *     y=3;
48    * }
49    * else
50    * {
51    *     isOdd=1;
52    *     y=4;
53    * } //Set y based on scanline evenness/oddness, not implemented yet
54    */
55 
56  /* for (x=0; x < strlen(frame->data); x++){
57 	 switch (frame->data[x])
58 	 {
59 	   case 0:
60 		  frame->data[x]++;
61 		  break;
62 	   case 255:
63 		  frame->data[x]--;
64 		  break;
65 	 }
66   }*/ // This doesn't work to fix the problem with the specks
67 
68   for (y = 3; y < frame->fmt.height - 3; y += 2)
69   {
70 	 for (x = 0; x < bytes; x++)
71 	 {
72 		frame->data[(y * bytes + x)] =
73 		   ((-frame->data[((y - 3) * bytes + x)]) +
74 			(9 * frame->data[((y - 1) * bytes + x)]) +
75 			(9 * frame->data[((y + 1) * bytes + x)]) +
76 			(-frame->data[((y + 3) * bytes + x)])) >> 4;
77 	 } // Basic algorithm borrowed from mplayer's libpostproc
78   }	// Angry math
79 }
80 
81 
82 static void *
init(struct ng_video_fmt * out)83 init (struct ng_video_fmt *out)
84 {
85   /* we will be using this variable soon enough */
86   static int isOdd = 0;
87   return &isOdd;
88 }
89 
90 static struct ng_video_buf *
frame(void * handle,struct ng_video_buf * frame)91 frame (void *handle, struct ng_video_buf *frame)
92 {
93   deinterlace (frame);
94   return frame;
95 }
96 
97 static void
fini(void * handle)98 fini (void *handle)
99 {
100   /* nothing to clean up */
101 }
102 
103 /* ------------------------------------------------------------------- */
104 
105 static struct ng_filter filter = {
106   .name ="cubic interpolation",
107   .fmts =
108     (1 << VIDEO_GRAY)			|
109     (1 << VIDEO_RGB15_NATIVE)		|
110     (1 << VIDEO_RGB16_NATIVE)		|
111     (1 << VIDEO_BGR24)			|
112     (1 << VIDEO_RGB24)			|
113     (1 << VIDEO_BGR32)			|
114     (1 << VIDEO_RGB32)			|
115     (1 << VIDEO_YUYV)			|
116     (1 << VIDEO_UYVY),
117   .init =		init,
118   .frame =		frame,
119   .fini =		fini,
120 };
121 
122 extern void ng_plugin_init (void);
123 void
ng_plugin_init(void)124 ng_plugin_init (void)
125 {
126   ng_filter_register (NG_PLUGIN_MAGIC,__FILE__,&filter);
127 }
128