diff options
Diffstat (limited to 'drivers/media/video/pwc/pwc-uncompress.c')
-rw-r--r-- | drivers/media/video/pwc/pwc-uncompress.c | 154 |
1 files changed, 73 insertions, 81 deletions
diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c index b37a89a163f9..5d82028ef942 100644 --- a/drivers/media/video/pwc/pwc-uncompress.c +++ b/drivers/media/video/pwc/pwc-uncompress.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* Linux driver for Philips webcam | 1 | /* Linux driver for Philips webcam |
2 | Decompression frontend. | 2 | Decompression frontend. |
3 | (C) 1999-2003 Nemosoft Unv. | 3 | (C) 1999-2003 Nemosoft Unv. |
4 | (C) 2004 Luc Saillard (luc@saillard.org) | 4 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
5 | 5 | ||
6 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 6 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
7 | driver and thus may have bugs that are not present in the original version. | 7 | driver and thus may have bugs that are not present in the original version. |
@@ -22,6 +22,8 @@ | |||
22 | You should have received a copy of the GNU General Public License | 22 | You should have received a copy of the GNU General Public License |
23 | along with this program; if not, write to the Free Software | 23 | along with this program; if not, write to the Free Software |
24 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 24 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
25 | |||
26 | vim: set ts=8: | ||
25 | */ | 27 | */ |
26 | 28 | ||
27 | #include <asm/current.h> | 29 | #include <asm/current.h> |
@@ -29,6 +31,8 @@ | |||
29 | 31 | ||
30 | #include "pwc.h" | 32 | #include "pwc.h" |
31 | #include "pwc-uncompress.h" | 33 | #include "pwc-uncompress.h" |
34 | #include "pwc-dec1.h" | ||
35 | #include "pwc-dec23.h" | ||
32 | 36 | ||
33 | int pwc_decompress(struct pwc_device *pdev) | 37 | int pwc_decompress(struct pwc_device *pdev) |
34 | { | 38 | { |
@@ -40,107 +44,95 @@ int pwc_decompress(struct pwc_device *pdev) | |||
40 | 44 | ||
41 | if (pdev == NULL) | 45 | if (pdev == NULL) |
42 | return -EFAULT; | 46 | return -EFAULT; |
43 | #if defined(__KERNEL__) && defined(PWC_MAGIC) | ||
44 | if (pdev->magic != PWC_MAGIC) { | ||
45 | Err("pwc_decompress(): magic failed.\n"); | ||
46 | return -EFAULT; | ||
47 | } | ||
48 | #endif | ||
49 | 47 | ||
50 | fbuf = pdev->read_frame; | 48 | fbuf = pdev->read_frame; |
51 | if (fbuf == NULL) | 49 | if (fbuf == NULL) |
52 | return -EFAULT; | 50 | return -EFAULT; |
53 | image = pdev->image_ptr[pdev->fill_image]; | 51 | image = pdev->image_data; |
54 | if (!image) | 52 | image += pdev->images[pdev->fill_image].offset; |
55 | return -EFAULT; | ||
56 | 53 | ||
57 | yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ | 54 | yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ |
58 | 55 | ||
59 | /* Raw format; that's easy... */ | 56 | /* Raw format; that's easy... */ |
60 | if (pdev->vpalette == VIDEO_PALETTE_RAW) | 57 | if (pdev->vpalette == VIDEO_PALETTE_RAW) |
61 | { | 58 | { |
62 | memcpy(image, yuv, pdev->frame_size); | 59 | struct pwc_raw_frame *raw_frame = image; |
60 | raw_frame->type = cpu_to_le16(pdev->type); | ||
61 | raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength); | ||
62 | /* cmd_buf is always 4 bytes, but sometimes, only the | ||
63 | * first 3 bytes is filled (Nala case). We can | ||
64 | * determine this using the type of the webcam */ | ||
65 | memcpy(raw_frame->cmd, pdev->cmd_buf, 4); | ||
66 | memcpy(raw_frame+1, yuv, pdev->frame_size); | ||
63 | return 0; | 67 | return 0; |
64 | } | 68 | } |
65 | 69 | ||
66 | if (pdev->vbandlength == 0) { | 70 | if (pdev->vbandlength == 0) { |
67 | /* Uncompressed mode. We copy the data into the output buffer, | 71 | /* Uncompressed mode. |
68 | using the viewport size (which may be larger than the image | 72 | * We copy the data into the output buffer, using the viewport |
69 | size). Unfortunately we have to do a bit of byte stuffing | 73 | * size (which may be larger than the image size). |
70 | to get the desired output format/size. | 74 | * Unfortunately we have to do a bit of byte stuffing to get |
75 | * the desired output format/size. | ||
76 | * | ||
77 | * We do some byte shuffling here to go from the | ||
78 | * native format to YUV420P. | ||
71 | */ | 79 | */ |
72 | /* | 80 | src = (u16 *)yuv; |
73 | * We do some byte shuffling here to go from the | 81 | n = pdev->view.x * pdev->view.y; |
74 | * native format to YUV420P. | 82 | |
75 | */ | 83 | /* offset in Y plane */ |
76 | src = (u16 *)yuv; | 84 | stride = pdev->view.x * pdev->offset.y + pdev->offset.x; |
77 | n = pdev->view.x * pdev->view.y; | 85 | dsty = (u16 *)(image + stride); |
78 | 86 | ||
79 | /* offset in Y plane */ | 87 | /* offsets in U/V planes */ |
80 | stride = pdev->view.x * pdev->offset.y + pdev->offset.x; | 88 | stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; |
81 | dsty = (u16 *)(image + stride); | 89 | dstu = (u16 *)(image + n + stride); |
82 | 90 | dstv = (u16 *)(image + n + n / 4 + stride); | |
83 | /* offsets in U/V planes */ | 91 | |
84 | stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; | 92 | /* increment after each line */ |
85 | dstu = (u16 *)(image + n + stride); | 93 | stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ |
86 | dstv = (u16 *)(image + n + n / 4 + stride); | 94 | |
87 | 95 | for (line = 0; line < pdev->image.y; line++) { | |
88 | /* increment after each line */ | 96 | for (col = 0; col < pdev->image.x; col += 4) { |
89 | stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ | 97 | *dsty++ = *src++; |
90 | 98 | *dsty++ = *src++; | |
91 | for (line = 0; line < pdev->image.y; line++) { | ||
92 | for (col = 0; col < pdev->image.x; col += 4) { | ||
93 | *dsty++ = *src++; | ||
94 | *dsty++ = *src++; | ||
95 | if (line & 1) | ||
96 | *dstv++ = *src++; | ||
97 | else | ||
98 | *dstu++ = *src++; | ||
99 | } | ||
100 | dsty += stride; | ||
101 | if (line & 1) | 99 | if (line & 1) |
102 | dstv += (stride >> 1); | 100 | *dstv++ = *src++; |
103 | else | 101 | else |
104 | dstu += (stride >> 1); | 102 | *dstu++ = *src++; |
105 | } | 103 | } |
104 | dsty += stride; | ||
105 | if (line & 1) | ||
106 | dstv += (stride >> 1); | ||
107 | else | ||
108 | dstu += (stride >> 1); | ||
109 | } | ||
110 | |||
111 | return 0; | ||
106 | } | 112 | } |
107 | else { | 113 | |
108 | /* Compressed; the decompressor routines will write the data | 114 | /* |
109 | in planar format immediately. | 115 | * Compressed; |
110 | */ | 116 | * the decompressor routines will write the data in planar format |
111 | int flags; | 117 | * immediately. |
112 | 118 | */ | |
113 | flags = PWCX_FLAG_PLANAR; | 119 | if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) { |
114 | if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) | 120 | PWC_ERROR("Mode Bayer is not supported for now\n"); |
115 | { | 121 | /* flags |= PWCX_FLAG_BAYER; */ |
116 | printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n"); | 122 | return -ENXIO; /* No such device or address: missing decompressor */ |
117 | flags |= PWCX_FLAG_BAYER; | 123 | } |
118 | return -ENXIO; /* No such device or address: missing decompressor */ | 124 | |
119 | } | 125 | if (DEVICE_USE_CODEC1(pdev->type)) { |
120 | 126 | ||
121 | #if 0 | 127 | /* TODO & FIXME */ |
122 | switch (pdev->type) | 128 | PWC_ERROR("This chipset is not supported for now\n"); |
123 | { | 129 | return -ENXIO; /* No such device or address: missing decompressor */ |
124 | case 675: | 130 | |
125 | case 680: | 131 | } else { |
126 | case 690: | 132 | pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR); |
127 | case 720: | ||
128 | case 730: | ||
129 | case 740: | ||
130 | case 750: | ||
131 | pwc_dec23_decompress(&pdev->image, &pdev->view, | ||
132 | &pdev->offset, yuv, image, flags, | ||
133 | pdev->decompress_data, pdev->vbandlength); | ||
134 | break; | ||
135 | case 645: | ||
136 | case 646: | ||
137 | /* TODO & FIXME */ | ||
138 | return -ENXIO; /* Missing decompressor */ | ||
139 | break; | ||
140 | } | ||
141 | #endif | ||
142 | } | 133 | } |
143 | return 0; | 134 | return 0; |
144 | } | 135 | } |
145 | 136 | ||
146 | 137 | ||
138 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||