Rev 846 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
846 | giacomo | 1 | /* Linux driver for Philips webcam |
2 | Decompression frontend. |
||
3 | (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl) |
||
4 | |||
5 | This program is free software; you can redistribute it and/or modify |
||
6 | it under the terms of the GNU General Public License as published by |
||
7 | the Free Software Foundation; either version 2 of the License, or |
||
8 | (at your option) any later version. |
||
9 | |||
10 | This program is distributed in the hope that it will be useful, |
||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 | GNU General Public License for more details. |
||
14 | |||
15 | You should have received a copy of the GNU General Public License |
||
16 | along with this program; if not, write to the Free Software |
||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
18 | */ |
||
19 | /* |
||
20 | This is where the decompression routines register and unregister |
||
21 | themselves. It also has a decompressor wrapper function. |
||
22 | */ |
||
23 | |||
24 | #include <asm/current.h> |
||
25 | #include <asm/types.h> |
||
26 | // #include <linux/sched.h> |
||
27 | |||
28 | #include "pwc.h" |
||
29 | #include "pwc-uncompress.h" |
||
30 | |||
31 | |||
32 | /* This contains a list of all registered decompressors */ |
||
33 | static LIST_HEAD(pwc_decompressor_list); |
||
34 | |||
35 | /* Should the pwc_decompress structure ever change, we increase the |
||
36 | version number so that we don't get nasty surprises, or can |
||
37 | dynamically adjust our structure. |
||
38 | */ |
||
39 | const int pwc_decompressor_version = PWC_MAJOR; |
||
40 | |||
41 | /* Add decompressor to list, ignoring duplicates */ |
||
42 | void pwc_register_decompressor(struct pwc_decompressor *pwcd) |
||
43 | { |
||
44 | if (pwc_find_decompressor(pwcd->type) == NULL) { |
||
45 | Trace(TRACE_PWCX, "Adding decompressor for model %d.\n", pwcd->type); |
||
46 | list_add_tail(&pwcd->pwcd_list, &pwc_decompressor_list); |
||
47 | } |
||
48 | } |
||
49 | |||
50 | /* Remove decompressor from list */ |
||
51 | void pwc_unregister_decompressor(int type) |
||
52 | { |
||
53 | struct pwc_decompressor *find; |
||
54 | |||
55 | find = pwc_find_decompressor(type); |
||
56 | if (find != NULL) { |
||
57 | Trace(TRACE_PWCX, "Removing decompressor for model %d.\n", type); |
||
58 | list_del(&find->pwcd_list); |
||
59 | } |
||
60 | } |
||
61 | |||
62 | /* Find decompressor in list */ |
||
63 | struct pwc_decompressor *pwc_find_decompressor(int type) |
||
64 | { |
||
65 | struct list_head *tmp; |
||
66 | struct pwc_decompressor *pwcd; |
||
67 | |||
68 | list_for_each(tmp, &pwc_decompressor_list) { |
||
69 | pwcd = list_entry(tmp, struct pwc_decompressor, pwcd_list); |
||
70 | if (pwcd->type == type) |
||
71 | return pwcd; |
||
72 | } |
||
73 | return NULL; |
||
74 | } |
||
75 | |||
76 | |||
77 | |||
78 | int pwc_decompress(struct pwc_device *pdev) |
||
79 | { |
||
80 | struct pwc_frame_buf *fbuf; |
||
81 | int n, line, col, stride; |
||
82 | void *yuv, *image; |
||
83 | u16 *src; |
||
84 | u16 *dsty, *dstu, *dstv; |
||
85 | |||
86 | if (pdev == NULL) |
||
87 | return -EFAULT; |
||
88 | #if defined(__KERNEL__) && defined(PWC_MAGIC) |
||
89 | if (pdev->magic != PWC_MAGIC) { |
||
90 | Err("pwc_decompress(): magic failed.\n"); |
||
91 | return -EFAULT; |
||
92 | } |
||
93 | #endif |
||
94 | |||
95 | fbuf = pdev->read_frame; |
||
96 | if (fbuf == NULL) |
||
97 | return -EFAULT; |
||
98 | image = pdev->image_ptr[pdev->fill_image]; |
||
99 | if (!image) |
||
100 | return -EFAULT; |
||
101 | |||
102 | yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ |
||
103 | |||
104 | /* Raw format; that's easy... */ |
||
105 | if (pdev->vpalette == VIDEO_PALETTE_RAW) |
||
106 | { |
||
107 | memcpy(image, yuv, pdev->frame_size); |
||
108 | return 0; |
||
109 | } |
||
110 | |||
111 | if (pdev->vbandlength == 0) { |
||
112 | /* Uncompressed mode. We copy the data into the output buffer, |
||
113 | using the viewport size (which may be larger than the image |
||
114 | size). Unfortunately we have to do a bit of byte stuffing |
||
115 | to get the desired output format/size. |
||
116 | */ |
||
117 | /* |
||
118 | * We do some byte shuffling here to go from the |
||
119 | * native format to YUV420P. |
||
120 | */ |
||
121 | src = (u16 *)yuv; |
||
122 | n = pdev->view.x * pdev->view.y; |
||
123 | |||
124 | /* offset in Y plane */ |
||
125 | stride = pdev->view.x * pdev->offset.y + pdev->offset.x; |
||
126 | dsty = (u16 *)(image + stride); |
||
127 | |||
128 | /* offsets in U/V planes */ |
||
129 | stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; |
||
130 | dstu = (u16 *)(image + n + stride); |
||
131 | dstv = (u16 *)(image + n + n / 4 + stride); |
||
132 | |||
133 | /* increment after each line */ |
||
134 | stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ |
||
135 | |||
136 | for (line = 0; line < pdev->image.y; line++) { |
||
137 | for (col = 0; col < pdev->image.x; col += 4) { |
||
138 | *dsty++ = *src++; |
||
139 | *dsty++ = *src++; |
||
140 | if (line & 1) |
||
141 | *dstv++ = *src++; |
||
142 | else |
||
143 | *dstu++ = *src++; |
||
144 | } |
||
145 | dsty += stride; |
||
146 | if (line & 1) |
||
147 | dstv += (stride >> 1); |
||
148 | else |
||
149 | dstu += (stride >> 1); |
||
150 | } |
||
151 | } |
||
152 | else { |
||
153 | /* Compressed; the decompressor routines will write the data |
||
154 | in planar format immediately. |
||
155 | */ |
||
156 | int flags; |
||
157 | |||
158 | flags = PWCX_FLAG_PLANAR; |
||
159 | if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) |
||
160 | flags |= PWCX_FLAG_BAYER; |
||
161 | |||
162 | if (pdev->decompressor) |
||
163 | pdev->decompressor->decompress( |
||
164 | &pdev->image, &pdev->view, &pdev->offset, |
||
165 | yuv, image, |
||
166 | flags, |
||
167 | pdev->decompress_data, pdev->vbandlength); |
||
168 | else |
||
169 | return -ENXIO; /* No such device or address: missing decompressor */ |
||
170 | } |
||
171 | return 0; |
||
172 | } |
||
173 | |||
174 | /* Make sure these functions are available for the decompressor plugin |
||
175 | both when this code is compiled into the kernel or as as module. |
||
176 | */ |
||
177 | |||
178 | EXPORT_SYMBOL_NOVERS(pwc_decompressor_version); |
||
179 | EXPORT_SYMBOL(pwc_register_decompressor); |
||
180 | EXPORT_SYMBOL(pwc_unregister_decompressor); |