author | mickeyl <mickeyl> | 2003-04-21 00:36:04 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-04-21 00:36:04 (UTC) |
commit | 74b6398e9b2e8d206310b3d61e6db4f1fa5e51a6 (patch) (unidiff) | |
tree | b9073d7b7deb36ff6572c9462fdcc047c1087cd0 | |
parent | 9163bfcc25b78477a75a153f2a75be30ad297c6a (diff) | |
download | opie-74b6398e9b2e8d206310b3d61e6db4f1fa5e51a6.zip opie-74b6398e9b2e8d206310b3d61e6db4f1fa5e51a6.tar.gz opie-74b6398e9b2e8d206310b3d61e6db4f1fa5e51a6.tar.bz2 |
Yahoo! Found the last three bugs in writing the avi stream. It now works :-D
-rw-r--r-- | noncore/multimedia/camera/avi.c | 3 | ||||
-rw-r--r-- | noncore/multimedia/camera/mainwindow.cpp | 10 |
2 files changed, 9 insertions, 4 deletions
diff --git a/noncore/multimedia/camera/avi.c b/noncore/multimedia/camera/avi.c index 0c757c9..77aba33 100644 --- a/noncore/multimedia/camera/avi.c +++ b/noncore/multimedia/camera/avi.c | |||
@@ -1,235 +1,236 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2003 Michael 'Mickey' Lauer. All rights reserved. | 2 | ** Copyright (C) 2003 Michael 'Mickey' Lauer. All rights reserved. |
3 | ** Based on work from Andrew Tridgell and the jpegtoavi project | 3 | ** Based on work from Andrew Tridgell and the jpegtoavi project |
4 | ** | 4 | ** |
5 | ** This file is part of Opie Environment. | 5 | ** This file is part of Opie Environment. |
6 | ** | 6 | ** |
7 | ** This file may be distributed and/or modified under the terms of the | 7 | ** This file may be distributed and/or modified under the terms of the |
8 | ** GNU General Public License version 2 as published by the Free Software | 8 | ** GNU General Public License version 2 as published by the Free Software |
9 | ** Foundation and appearing in the file LICENSE.GPL included in the | 9 | ** Foundation and appearing in the file LICENSE.GPL included in the |
10 | ** packaging of this file. | 10 | ** packaging of this file. |
11 | ** | 11 | ** |
12 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 12 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
13 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 13 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
14 | ** | 14 | ** |
15 | **********************************************************************/ | 15 | **********************************************************************/ |
16 | 16 | ||
17 | #include "avi.h" | 17 | #include "avi.h" |
18 | 18 | ||
19 | #include <string.h> | 19 | #include <string.h> |
20 | #include <stdio.h> | 20 | #include <stdio.h> |
21 | 21 | ||
22 | int nframes; | 22 | int nframes; |
23 | int totalsize; | 23 | int totalsize; |
24 | unsigned int* sizes; | 24 | unsigned int* sizes; |
25 | 25 | ||
26 | void fprint_quartet(int fd, unsigned int i) | 26 | void fprint_quartet(int fd, unsigned int i) |
27 | { | 27 | { |
28 | char data[4]; | 28 | char data[4]; |
29 | 29 | ||
30 | data[0] = (char) i%0x100; | 30 | data[0] = (char) i%0x100; |
31 | i /= 0x100; | 31 | i /= 0x100; |
32 | data[1] = (char) i%0x100; | 32 | data[1] = (char) i%0x100; |
33 | i /= 0x100; | 33 | i /= 0x100; |
34 | data[2] = (char) i%0x100; | 34 | data[2] = (char) i%0x100; |
35 | i /= 0x100; | 35 | i /= 0x100; |
36 | data[3] = (char) i%0x100; | 36 | data[3] = (char) i%0x100; |
37 | 37 | ||
38 | write( fd, &data, 4 ); | 38 | write( fd, &data, 4 ); |
39 | } | 39 | } |
40 | 40 | ||
41 | // start writing an AVI file | 41 | // start writing an AVI file |
42 | 42 | ||
43 | void avi_start(int fd, int frames) | 43 | void avi_start(int fd, int frames) |
44 | { | 44 | { |
45 | int ofs = sizeof(struct riff_head)+ | 45 | int ofs = sizeof(struct riff_head)+ |
46 | sizeof(struct list_head)+ | 46 | sizeof(struct list_head)+ |
47 | sizeof(struct avi_head)+ | 47 | sizeof(struct avi_head)+ |
48 | sizeof(struct list_head)+ | 48 | sizeof(struct list_head)+ |
49 | sizeof(struct stream_head)+ | 49 | sizeof(struct stream_head)+ |
50 | sizeof(struct frame_head)+ | 50 | sizeof(struct frame_head)+ |
51 | sizeof(struct list_head)+ | 51 | sizeof(struct list_head)+ |
52 | sizeof(struct dmlh_head)+ | 52 | sizeof(struct dmlh_head)+ |
53 | sizeof(struct list_head); | 53 | sizeof(struct list_head); |
54 | 54 | ||
55 | printf( "avi_start: frames = %d\n", frames ); | 55 | printf( "avi_start: frames = %d\n", frames ); |
56 | 56 | ||
57 | lseek(fd, ofs, SEEK_SET); | 57 | lseek(fd, ofs, SEEK_SET); |
58 | 58 | ||
59 | nframes = 0; | 59 | nframes = 0; |
60 | totalsize = 0; | 60 | totalsize = 0; |
61 | 61 | ||
62 | sizes = (unsigned int*) calloc( sizeof(unsigned int), frames ); // hold size of each frame | 62 | sizes = (unsigned int*) calloc( sizeof(unsigned int), frames ); // hold size of each frame |
63 | } | 63 | } |
64 | 64 | ||
65 | // add a jpeg frame to an AVI file | 65 | // add a jpeg frame to an AVI file |
66 | void avi_add(int fd, u8 *buf, int size) | 66 | void avi_add(int fd, u8 *buf, int size) |
67 | { | 67 | { |
68 | struct db_head db = {"00db", 0}; | 68 | struct db_head db = {"00db", 0}; |
69 | 69 | ||
70 | printf( "avi_add: nframes = %d, totalsize = %d, size = %d\n", nframes, totalsize, size ); | 70 | printf( "avi_add: nframes = %d, totalsize = %d, size = %d\n", nframes, totalsize, size ); |
71 | 71 | ||
72 | // overwrite JFIF type with AVI1 | 72 | // overwrite JFIF type with AVI1 |
73 | buf[6]='A'; | 73 | buf[6]='A'; |
74 | buf[7]='V'; | 74 | buf[7]='V'; |
75 | buf[8]='I'; | 75 | buf[8]='I'; |
76 | buf[9]='1'; | 76 | buf[9]='1'; |
77 | 77 | ||
78 | while( size%4 ) size++; // align 0 modulo 4*/ | 78 | while( size%4 ) size++; // align 0 modulo 4*/ |
79 | db.size = size; | 79 | db.size = size; |
80 | 80 | ||
81 | write( fd, &db, sizeof(db) ); | 81 | write( fd, &db, sizeof(db) ); |
82 | write( fd, buf, size ); | 82 | write( fd, buf, size ); |
83 | 83 | ||
84 | sizes[nframes] = size; | 84 | sizes[nframes] = size; |
85 | 85 | ||
86 | nframes++; | 86 | nframes++; |
87 | totalsize += size; // total frame size | 87 | totalsize += size; // total frame size |
88 | } | 88 | } |
89 | 89 | ||
90 | // finish writing the AVI file - filling in the header | 90 | // finish writing the AVI file - filling in the header |
91 | void avi_end(int fd, int width, int height, int fps) | 91 | void avi_end(int fd, int width, int height, int fps) |
92 | { | 92 | { |
93 | struct idx1_head idx = {"idx1", 16*nframes }; | 93 | struct idx1_head idx = {"idx1", 16*nframes }; |
94 | struct db_head db = {"00db", 0}; | 94 | struct db_head db = {"00db", 0}; |
95 | struct riff_head rh = { "RIFF", 0, "AVI "}; | 95 | struct riff_head rh = { "RIFF", 0, "AVI "}; |
96 | struct list_head lh1 = {"LIST", 0, "hdrl"}; | 96 | struct list_head lh1 = {"LIST", 0, "hdrl"}; |
97 | struct avi_head ah; | 97 | struct avi_head ah; |
98 | struct list_head lh2 = {"LIST", 0, "strl"}; | 98 | struct list_head lh2 = {"LIST", 0, "strl"}; |
99 | struct stream_head sh; | 99 | struct stream_head sh; |
100 | struct frame_head fh; | 100 | struct frame_head fh; |
101 | struct list_head lh3 = {"LIST", 0, "odml" }; | 101 | struct list_head lh3 = {"LIST", 0, "odml" }; |
102 | struct dmlh_head dh = {"dmlh", 4, nframes }; | 102 | struct dmlh_head dh = {"dmlh", 4, nframes }; |
103 | struct list_head lh4 = {"LIST", 0, "movi"}; | 103 | struct list_head lh4 = {"LIST", 0, "movi"}; |
104 | int i; | 104 | int i; |
105 | unsigned int offset = 4; | 105 | unsigned int offset = 4; |
106 | 106 | ||
107 | printf( "avi_end: nframes = %d, fps = %d\n", nframes, fps ); | 107 | printf( "avi_end: nframes = %d, fps = %d\n", nframes, fps ); |
108 | 108 | ||
109 | // write index | 109 | // write index |
110 | 110 | ||
111 | write(fd, &idx, sizeof(idx)); | 111 | write(fd, &idx, sizeof(idx)); |
112 | 112 | ||
113 | for ( i = 0; i < nframes; i++ ) | 113 | for ( i = 0; i < nframes; i++ ) |
114 | { | 114 | { |
115 | write(fd, &db, 4 ); // only need the 00db | 115 | write(fd, &db, 4 ); // only need the 00db |
116 | fprint_quartet( fd, 18 ); // ??? | 116 | fprint_quartet( fd, 18 ); // ??? |
117 | fprint_quartet( fd, offset ); | 117 | fprint_quartet( fd, offset ); |
118 | fprint_quartet( fd, sizes[i] ); | 118 | fprint_quartet( fd, sizes[i] ); |
119 | offset += sizes[i]; | 119 | offset += sizes[i] + 8; //+8 (for the additional header) |
120 | } | 120 | } |
121 | 121 | ||
122 | free( sizes ); | 122 | free( sizes ); |
123 | 123 | ||
124 | bzero( &ah, sizeof(ah) ); | 124 | bzero( &ah, sizeof(ah) ); |
125 | strcpy(ah.avih, "avih"); | 125 | strcpy(ah.avih, "avih"); |
126 | ah.time = 1000000 / fps; | 126 | ah.time = 1000000 / fps; |
127 | ah.maxbytespersec = 1000000.0*(totalsize/nframes)/ah.time; | 127 | ah.maxbytespersec = 1000000.0*(totalsize/nframes)/ah.time; |
128 | ah.nframes = nframes; | ||
128 | ah.numstreams = 1; | 129 | ah.numstreams = 1; |
129 | ah.flags = AVIF_HASINDEX; | 130 | ah.flags = AVIF_HASINDEX; |
130 | ah.width = width; | 131 | ah.width = width; |
131 | ah.height = height; | 132 | ah.height = height; |
132 | 133 | ||
133 | bzero(&sh, sizeof(sh)); | 134 | bzero(&sh, sizeof(sh)); |
134 | strcpy(sh.strh, "strh"); | 135 | strcpy(sh.strh, "strh"); |
135 | strcpy(sh.vids, "vids"); | 136 | strcpy(sh.vids, "vids"); |
136 | strcpy(sh.codec, "MJPG"); | 137 | strcpy(sh.codec, "MJPG"); |
137 | sh.scale = ah.time; | 138 | sh.scale = ah.time; |
138 | sh.rate = 1000000; | 139 | sh.rate = 1000000; |
139 | sh.length = nframes; | 140 | sh.length = nframes; |
140 | 141 | ||
141 | bzero(&fh, sizeof(fh)); | 142 | bzero(&fh, sizeof(fh)); |
142 | strcpy(fh.strf, "strf"); | 143 | strcpy(fh.strf, "strf"); |
143 | fh.width = width; | 144 | fh.width = width; |
144 | fh.height = height; | 145 | fh.height = height; |
145 | fh.planes = 1; | 146 | fh.planes = 1; |
146 | fh.bitcount = 24; | 147 | fh.bitcount = 24; |
147 | strcpy(fh.codec,"MJPG"); | 148 | strcpy(fh.codec,"MJPG"); |
148 | fh.unpackedsize = 3*width*height; | 149 | fh.unpackedsize = 3*width*height; |
149 | 150 | ||
150 | rh.size = sizeof(lh1)+sizeof(ah)+sizeof(lh2)+sizeof(sh)+ | 151 | rh.size = sizeof(lh1)+sizeof(ah)+sizeof(lh2)+sizeof(sh)+ |
151 | sizeof(fh)+sizeof(lh3)+sizeof(dh)+sizeof(lh4)+ | 152 | sizeof(fh)+sizeof(lh3)+sizeof(dh)+sizeof(lh4)+ |
152 | nframes*sizeof(struct db_head)+ | 153 | nframes*sizeof(struct db_head)+ |
153 | totalsize + sizeof(struct idx1_head)+ (16*nframes) +4; // FIXME:16 bytes per nframe // the '4' - what for??? | 154 | totalsize + sizeof(struct idx1_head)+ (16*nframes) +4; // FIXME:16 bytes per nframe // the '4' - what for??? |
154 | 155 | ||
155 | lh1.size = 4+sizeof(ah)+sizeof(lh2)+sizeof(sh)+sizeof(fh)+sizeof(lh3)+sizeof(dh); | 156 | lh1.size = 4+sizeof(ah)+sizeof(lh2)+sizeof(sh)+sizeof(fh)+sizeof(lh3)+sizeof(dh); |
156 | ah.size = sizeof(ah)-8; | 157 | ah.size = sizeof(ah)-8; |
157 | lh2.size = 4+sizeof(sh)+sizeof(fh)+sizeof(lh3)+sizeof(dh); //4+sizeof(sh)+sizeof(fh); | 158 | lh2.size = 4+sizeof(sh)+sizeof(fh)+sizeof(lh3)+sizeof(dh); //4+sizeof(sh)+sizeof(fh); |
158 | sh.size = sizeof(sh)-8; | 159 | sh.size = sizeof(sh)-8; |
159 | fh.size = sizeof(fh)-8; | 160 | fh.size = sizeof(fh)-8; |
160 | fh.size2 = fh.size; | 161 | fh.size2 = fh.size; |
161 | lh3.size = 4+sizeof(dh); | 162 | lh3.size = 4+sizeof(dh); |
162 | lh4.size = 4+ nframes*sizeof(struct db_head)+ totalsize; | 163 | lh4.size = 4+ nframes*sizeof(struct db_head)+ totalsize; |
163 | 164 | ||
164 | lseek(fd, 0, SEEK_SET); | 165 | lseek(fd, 0, SEEK_SET); |
165 | 166 | ||
166 | write(fd, &rh, sizeof(rh)); | 167 | write(fd, &rh, sizeof(rh)); |
167 | write(fd, &lh1, sizeof(lh1)); | 168 | write(fd, &lh1, sizeof(lh1)); |
168 | write(fd, &ah, sizeof(ah)); | 169 | write(fd, &ah, sizeof(ah)); |
169 | write(fd, &lh2, sizeof(lh2)); | 170 | write(fd, &lh2, sizeof(lh2)); |
170 | write(fd, &sh, sizeof(sh)); | 171 | write(fd, &sh, sizeof(sh)); |
171 | write(fd, &fh, sizeof(fh)); | 172 | write(fd, &fh, sizeof(fh)); |
172 | write(fd, &lh3, sizeof(lh3)); | 173 | write(fd, &lh3, sizeof(lh3)); |
173 | write(fd, &dh, sizeof(dh)); | 174 | write(fd, &dh, sizeof(dh)); |
174 | write(fd, &lh4, sizeof(lh4)); | 175 | write(fd, &lh4, sizeof(lh4)); |
175 | } | 176 | } |
176 | 177 | ||
177 | 178 | ||
178 | /* NOTE: This is not a general purpose routine - it is meant to only | 179 | /* NOTE: This is not a general purpose routine - it is meant to only |
179 | cope with AVIs saved using the other functions in this file | 180 | cope with AVIs saved using the other functions in this file |
180 | void avi_explode(char *fname) | 181 | void avi_explode(char *fname) |
181 | { | 182 | { |
182 | struct riff_head rh; | 183 | struct riff_head rh; |
183 | struct list_head lh1; | 184 | struct list_head lh1; |
184 | struct avi_head ah; | 185 | struct avi_head ah; |
185 | struct list_head lh2; | 186 | struct list_head lh2; |
186 | struct stream_head sh; | 187 | struct stream_head sh; |
187 | struct frame_head fh; | 188 | struct frame_head fh; |
188 | struct list_head lh3; | 189 | struct list_head lh3; |
189 | int hsize, qsize; | 190 | int hsize, qsize; |
190 | u16 *htables = jpeg_huffman_tables(&hsize); | 191 | u16 *htables = jpeg_huffman_tables(&hsize); |
191 | u16 *qtables = jpeg_quantisation_tables(&qsize, image_quality); | 192 | u16 *qtables = jpeg_quantisation_tables(&qsize, image_quality); |
192 | int fd, i; | 193 | int fd, i; |
193 | 194 | ||
194 | fd = open(fname,O_RDONLY); | 195 | fd = open(fname,O_RDONLY); |
195 | if (fd == -1) { | 196 | if (fd == -1) { |
196 | perror(fname); | 197 | perror(fname); |
197 | return; | 198 | return; |
198 | } | 199 | } |
199 | 200 | ||
200 | read(fd, &rh, sizeof(rh)); | 201 | read(fd, &rh, sizeof(rh)); |
201 | read(fd, &lh1, sizeof(lh1)); | 202 | read(fd, &lh1, sizeof(lh1)); |
202 | read(fd, &ah, sizeof(ah)); | 203 | read(fd, &ah, sizeof(ah)); |
203 | read(fd, &lh2, sizeof(lh2)); | 204 | read(fd, &lh2, sizeof(lh2)); |
204 | read(fd, &sh, sizeof(sh)); | 205 | read(fd, &sh, sizeof(sh)); |
205 | read(fd, &fh, sizeof(fh)); | 206 | read(fd, &fh, sizeof(fh)); |
206 | read(fd, &lh3, sizeof(lh3)); | 207 | read(fd, &lh3, sizeof(lh3)); |
207 | 208 | ||
208 | for (i=0; ; i++) { | 209 | for (i=0; ; i++) { |
209 | u8 buf[500*1024]; | 210 | u8 buf[500*1024]; |
210 | struct db_head db; | 211 | struct db_head db; |
211 | char fname[100]; | 212 | char fname[100]; |
212 | int fd2; | 213 | int fd2; |
213 | 214 | ||
214 | if (read(fd, &db, sizeof(db)) != sizeof(db) || | 215 | if (read(fd, &db, sizeof(db)) != sizeof(db) || |
215 | read(fd, buf, db.size) != db.size) break; | 216 | read(fd, buf, db.size) != db.size) break; |
216 | 217 | ||
217 | snprintf(fname, sizeof(fname)-1,"frame.%d", i); | 218 | snprintf(fname, sizeof(fname)-1,"frame.%d", i); |
218 | 219 | ||
219 | fd2 = open(fname,O_WRONLY|O_CREAT, 0644); | 220 | fd2 = open(fname,O_WRONLY|O_CREAT, 0644); |
220 | if (fd2 == -1) { | 221 | if (fd2 == -1) { |
221 | perror(fname); | 222 | perror(fname); |
222 | continue; | 223 | continue; |
223 | } | 224 | } |
224 | write(fd2, buf, 2); | 225 | write(fd2, buf, 2); |
225 | write(fd2, qtables, qsize); | 226 | write(fd2, qtables, qsize); |
226 | write(fd2, htables, hsize); | 227 | write(fd2, htables, hsize); |
227 | write(fd2, buf+2, db.size-2); | 228 | write(fd2, buf+2, db.size-2); |
228 | close(fd2); | 229 | close(fd2); |
229 | } | 230 | } |
230 | close(fd); | 231 | close(fd); |
231 | printf("exploded %d frames\n", i); | 232 | printf("exploded %d frames\n", i); |
232 | } | 233 | } |
233 | 234 | ||
234 | */ | 235 | */ |
235 | 236 | ||
diff --git a/noncore/multimedia/camera/mainwindow.cpp b/noncore/multimedia/camera/mainwindow.cpp index e27a50e..7e60e16 100644 --- a/noncore/multimedia/camera/mainwindow.cpp +++ b/noncore/multimedia/camera/mainwindow.cpp | |||
@@ -1,551 +1,555 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved. | 2 | ** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Opie Environment. | 4 | ** This file is part of Opie Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | **********************************************************************/ | 14 | **********************************************************************/ |
15 | 15 | ||
16 | #include "mainwindow.h" | 16 | #include "mainwindow.h" |
17 | #include "previewwidget.h" | 17 | #include "previewwidget.h" |
18 | #include "zcameraio.h" | 18 | #include "zcameraio.h" |
19 | #include "imageio.h" | 19 | #include "imageio.h" |
20 | #include "avi.h" | 20 | #include "avi.h" |
21 | 21 | ||
22 | #include <qapplication.h> | 22 | #include <qapplication.h> |
23 | #include <qaction.h> | 23 | #include <qaction.h> |
24 | #include <qvbox.h> | 24 | #include <qvbox.h> |
25 | #include <qcombobox.h> | 25 | #include <qcombobox.h> |
26 | #include <qcursor.h> | 26 | #include <qcursor.h> |
27 | #include <qdatastream.h> | 27 | #include <qdatastream.h> |
28 | #include <qfile.h> | 28 | #include <qfile.h> |
29 | #include <qimage.h> | 29 | #include <qimage.h> |
30 | #include <qlabel.h> | 30 | #include <qlabel.h> |
31 | #include <qpopupmenu.h> | 31 | #include <qpopupmenu.h> |
32 | #include <qprogressbar.h> | 32 | #include <qprogressbar.h> |
33 | #include <qpushbutton.h> | 33 | #include <qpushbutton.h> |
34 | #include <qmessagebox.h> | 34 | #include <qmessagebox.h> |
35 | #include <qlayout.h> | 35 | #include <qlayout.h> |
36 | #include <qdirectpainter_qws.h> | 36 | #include <qdirectpainter_qws.h> |
37 | #include <qpe/global.h> | 37 | #include <qpe/global.h> |
38 | #include <qpe/resource.h> | 38 | #include <qpe/resource.h> |
39 | #include <qpe/qcopenvelope_qws.h> | 39 | #include <qpe/qcopenvelope_qws.h> |
40 | #include <opie/ofiledialog.h> | 40 | #include <opie/ofiledialog.h> |
41 | #include <opie/odevice.h> | 41 | #include <opie/odevice.h> |
42 | using namespace Opie; | 42 | using namespace Opie; |
43 | #include <opie2/odebug.h> | 43 | #include <opie2/odebug.h> |
44 | 44 | ||
45 | #include <assert.h> | 45 | #include <assert.h> |
46 | #include <sys/types.h> | 46 | #include <sys/types.h> |
47 | #include <sys/stat.h> | 47 | #include <sys/stat.h> |
48 | #include <fcntl.h> | 48 | #include <fcntl.h> |
49 | #include <string.h> | 49 | #include <string.h> |
50 | #include <errno.h> | 50 | #include <errno.h> |
51 | #include <unistd.h> | 51 | #include <unistd.h> |
52 | 52 | ||
53 | #define CAPTUREFILE "/tmp/capture.dat" | 53 | #define CAPTUREFILE "/tmp/capture.dat" |
54 | #define OUTPUTFILE "/tmp/output.avi" | 54 | #define OUTPUTFILE "/tmp/output.avi" |
55 | 55 | ||
56 | CameraMainWindow::CameraMainWindow( QWidget * parent, const char * name, WFlags f ) | 56 | CameraMainWindow::CameraMainWindow( QWidget * parent, const char * name, WFlags f ) |
57 | :QMainWindow( parent, name, f ), | 57 | :QMainWindow( parent, name, f ), |
58 | _rotation( 270 ), // FIXME: get this from current settings (ODevice?) | 58 | _rotation( 270 ), // FIXME: get this from current settings (ODevice?) |
59 | _capturing( false ), | 59 | _capturing( false ), |
60 | _pics( 0 ), _videos( 0 ) | 60 | _pics( 0 ), _videos( 0 ) |
61 | { | 61 | { |
62 | #ifdef QT_NO_DEBUG | 62 | #ifdef QT_NO_DEBUG |
63 | if ( !ZCameraIO::instance()->isOpen() ) | 63 | if ( !ZCameraIO::instance()->isOpen() ) |
64 | { | 64 | { |
65 | QVBox* v = new QVBox( this ); | 65 | QVBox* v = new QVBox( this ); |
66 | v->setMargin( 10 ); | 66 | v->setMargin( 10 ); |
67 | QLabel* l1 = new QLabel( v ); | 67 | QLabel* l1 = new QLabel( v ); |
68 | l1->setPixmap( Resource::loadPixmap( "camera/error" ) ); | 68 | l1->setPixmap( Resource::loadPixmap( "camera/error" ) ); |
69 | QLabel* l2 = new QLabel( v ); | 69 | QLabel* l2 = new QLabel( v ); |
70 | l2->setText( "<b>Sorry. could not detect your camera :-(</b><p>" | 70 | l2->setText( "<b>Sorry. could not detect your camera :-(</b><p>" |
71 | "* Is the sharpzdc_cs module loaded ?<br>" | 71 | "* Is the sharpzdc_cs module loaded ?<br>" |
72 | "* Is /dev/sharpzdc read/writable ?<p>" ); | 72 | "* Is /dev/sharpzdc read/writable ?<p>" ); |
73 | connect( new QPushButton( "Exit", v ), SIGNAL( clicked() ), this, SLOT( close() ) ); | 73 | connect( new QPushButton( "Exit", v ), SIGNAL( clicked() ), this, SLOT( close() ) ); |
74 | setCentralWidget( v ); | 74 | setCentralWidget( v ); |
75 | return; | 75 | return; |
76 | } | 76 | } |
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | init(); | 79 | init(); |
80 | 80 | ||
81 | _rotation = 270; //TODO: grab these from the actual settings | 81 | _rotation = 270; //TODO: grab these from the actual settings |
82 | 82 | ||
83 | preview = new PreviewWidget( this, "camera preview widget" ); | 83 | preview = new PreviewWidget( this, "camera preview widget" ); |
84 | //setCentralWidget( preview ); <--- don't do this! | 84 | //setCentralWidget( preview ); <--- don't do this! |
85 | preview->resize( QSize( 240, 288 ) ); | 85 | preview->resize( QSize( 240, 288 ) ); |
86 | preview->show(); | 86 | preview->show(); |
87 | 87 | ||
88 | // construct a System Channel to receive setRotation messages | 88 | // construct a System Channel to receive setRotation messages |
89 | _sysChannel = new QCopChannel( "QPE/System", this ); | 89 | _sysChannel = new QCopChannel( "QPE/System", this ); |
90 | connect( _sysChannel, SIGNAL( received( const QCString&, const QByteArray& ) ), | 90 | connect( _sysChannel, SIGNAL( received( const QCString&, const QByteArray& ) ), |
91 | this, SLOT( systemMessage( const QCString&, const QByteArray& ) ) ); | 91 | this, SLOT( systemMessage( const QCString&, const QByteArray& ) ) ); |
92 | 92 | ||
93 | connect( preview, SIGNAL( contextMenuRequested() ), this, SLOT( showContextMenu() ) ); | 93 | connect( preview, SIGNAL( contextMenuRequested() ), this, SLOT( showContextMenu() ) ); |
94 | 94 | ||
95 | connect( ZCameraIO::instance(), SIGNAL( shutterClicked() ), this, SLOT( shutterClicked() ) ); | 95 | connect( ZCameraIO::instance(), SIGNAL( shutterClicked() ), this, SLOT( shutterClicked() ) ); |
96 | 96 | ||
97 | updateCaption(); | 97 | updateCaption(); |
98 | 98 | ||
99 | }; | 99 | }; |
100 | 100 | ||
101 | 101 | ||
102 | CameraMainWindow::~CameraMainWindow() | 102 | CameraMainWindow::~CameraMainWindow() |
103 | { | 103 | { |
104 | } | 104 | } |
105 | 105 | ||
106 | 106 | ||
107 | void CameraMainWindow::init() | 107 | void CameraMainWindow::init() |
108 | { | 108 | { |
109 | // TODO: Save this stuff in config | 109 | // TODO: Save this stuff in config |
110 | flip = 'A'; // auto | 110 | flip = 'A'; // auto |
111 | quality = 50; | 111 | quality = 50; |
112 | zoom = 1; | 112 | zoom = 1; |
113 | captureX = 480; | 113 | captureX = 480; |
114 | captureY = 640; | 114 | captureY = 640; |
115 | captureFormat = "JPEG"; | 115 | captureFormat = "JPEG"; |
116 | 116 | ||
117 | resog = new QActionGroup( 0, "reso", true ); | 117 | resog = new QActionGroup( 0, "reso", true ); |
118 | resog->setToggleAction( true ); | 118 | resog->setToggleAction( true ); |
119 | new QAction( " 64 x 48", 0, 0, resog, 0, true ); | 119 | new QAction( " 64 x 48", 0, 0, resog, 0, true ); |
120 | new QAction( "128 x 96", 0, 0, resog, 0, true ); | 120 | new QAction( "128 x 96", 0, 0, resog, 0, true ); |
121 | new QAction( "192 x 144", 0, 0, resog, 0, true ); | 121 | new QAction( "192 x 144", 0, 0, resog, 0, true ); |
122 | new QAction( "256 x 192", 0, 0, resog, 0, true ); | 122 | new QAction( "256 x 192", 0, 0, resog, 0, true ); |
123 | new QAction( "320 x 240", 0, 0, resog, 0, true ); | 123 | new QAction( "320 x 240", 0, 0, resog, 0, true ); |
124 | new QAction( "384 x 288", 0, 0, resog, 0, true ); | 124 | new QAction( "384 x 288", 0, 0, resog, 0, true ); |
125 | new QAction( "448 x 336", 0, 0, resog, 0, true ); | 125 | new QAction( "448 x 336", 0, 0, resog, 0, true ); |
126 | new QAction( "512 x 384", 0, 0, resog, 0, true ); | 126 | new QAction( "512 x 384", 0, 0, resog, 0, true ); |
127 | new QAction( "576 x 432", 0, 0, resog, 0, true ); | 127 | new QAction( "576 x 432", 0, 0, resog, 0, true ); |
128 | ( new QAction( "640 x 480", 0, 0, resog, 0, true ) )->setOn( true ); | 128 | ( new QAction( "640 x 480", 0, 0, resog, 0, true ) )->setOn( true ); |
129 | 129 | ||
130 | qualityg = new QActionGroup( 0, "quality", true ); | 130 | qualityg = new QActionGroup( 0, "quality", true ); |
131 | qualityg->setToggleAction( true ); | 131 | qualityg->setToggleAction( true ); |
132 | new QAction( " 0 (minimal)", 0, 0, qualityg, 0, true ); | 132 | new QAction( " 0 (minimal)", 0, 0, qualityg, 0, true ); |
133 | new QAction( " 25 (low)", 0, 0, qualityg, 0, true ); | 133 | new QAction( " 25 (low)", 0, 0, qualityg, 0, true ); |
134 | ( new QAction( " 50 (good)", 0, 0, qualityg, 0, true ) )->setOn( true ); | 134 | ( new QAction( " 50 (good)", 0, 0, qualityg, 0, true ) )->setOn( true ); |
135 | new QAction( " 75 (better)", 0, 0, qualityg, 0, true ); | 135 | new QAction( " 75 (better)", 0, 0, qualityg, 0, true ); |
136 | new QAction( "100 (best)", 0, 0, qualityg, 0, true ); | 136 | new QAction( "100 (best)", 0, 0, qualityg, 0, true ); |
137 | 137 | ||
138 | zoomg = new QActionGroup( 0, "zoom", true ); | 138 | zoomg = new QActionGroup( 0, "zoom", true ); |
139 | zoomg->setToggleAction( true ); | 139 | zoomg->setToggleAction( true ); |
140 | ( new QAction( "x 1", 0, 0, zoomg, 0, true ) )->setOn( true ); | 140 | ( new QAction( "x 1", 0, 0, zoomg, 0, true ) )->setOn( true ); |
141 | new QAction( "x 2", 0, 0, zoomg, 0, true ); | 141 | new QAction( "x 2", 0, 0, zoomg, 0, true ); |
142 | 142 | ||
143 | flipg = new QActionGroup( 0, "flip", true ); | 143 | flipg = new QActionGroup( 0, "flip", true ); |
144 | flipg->setToggleAction( true ); | 144 | flipg->setToggleAction( true ); |
145 | ( new QAction( "Auto (recommended)", 0, 0, flipg, 0, true ) )->setOn( true ); | 145 | ( new QAction( "Auto (recommended)", 0, 0, flipg, 0, true ) )->setOn( true ); |
146 | new QAction( "0 (always off)", 0, 0, flipg, 0, true ); | 146 | new QAction( "0 (always off)", 0, 0, flipg, 0, true ); |
147 | new QAction( "X (always horizontal)", 0, 0, flipg, 0, true ); | 147 | new QAction( "X (always horizontal)", 0, 0, flipg, 0, true ); |
148 | new QAction( "Y (always vertical)", 0, 0, flipg, 0, true ); | 148 | new QAction( "Y (always vertical)", 0, 0, flipg, 0, true ); |
149 | new QAction( "* (always both)", 0, 0, flipg, 0, true ); | 149 | new QAction( "* (always both)", 0, 0, flipg, 0, true ); |
150 | 150 | ||
151 | outputg = new QActionGroup( 0, "output", true ); | 151 | outputg = new QActionGroup( 0, "output", true ); |
152 | outputg->setToggleAction( true ); | 152 | outputg->setToggleAction( true ); |
153 | ( new QAction( "JPEG", 0, 0, outputg, 0, true ) )->setOn( true ); | 153 | ( new QAction( "JPEG", 0, 0, outputg, 0, true ) )->setOn( true ); |
154 | new QAction( "PNG", 0, 0, outputg, 0, true ); | 154 | new QAction( "PNG", 0, 0, outputg, 0, true ); |
155 | new QAction( "BMP", 0, 0, outputg, 0, true ); | 155 | new QAction( "BMP", 0, 0, outputg, 0, true ); |
156 | new QAction( "AVI", 0, 0, outputg, 0, true ); | 156 | new QAction( "AVI", 0, 0, outputg, 0, true ); |
157 | 157 | ||
158 | connect( resog, SIGNAL( selected(QAction*) ), this, SLOT( resoMenuItemClicked(QAction*) ) ); | 158 | connect( resog, SIGNAL( selected(QAction*) ), this, SLOT( resoMenuItemClicked(QAction*) ) ); |
159 | connect( qualityg, SIGNAL( selected(QAction*) ), this, SLOT( qualityMenuItemClicked(QAction*) ) ); | 159 | connect( qualityg, SIGNAL( selected(QAction*) ), this, SLOT( qualityMenuItemClicked(QAction*) ) ); |
160 | connect( zoomg, SIGNAL( selected(QAction*) ), this, SLOT( zoomMenuItemClicked(QAction*) ) ); | 160 | connect( zoomg, SIGNAL( selected(QAction*) ), this, SLOT( zoomMenuItemClicked(QAction*) ) ); |
161 | connect( flipg, SIGNAL( selected(QAction*) ), this, SLOT( flipMenuItemClicked(QAction*) ) ); | 161 | connect( flipg, SIGNAL( selected(QAction*) ), this, SLOT( flipMenuItemClicked(QAction*) ) ); |
162 | connect( outputg, SIGNAL( selected(QAction*) ), this, SLOT( outputMenuItemClicked(QAction*) ) ); | 162 | connect( outputg, SIGNAL( selected(QAction*) ), this, SLOT( outputMenuItemClicked(QAction*) ) ); |
163 | 163 | ||
164 | } | 164 | } |
165 | 165 | ||
166 | 166 | ||
167 | void CameraMainWindow::systemMessage( const QCString& msg, const QByteArray& data ) | 167 | void CameraMainWindow::systemMessage( const QCString& msg, const QByteArray& data ) |
168 | { | 168 | { |
169 | int _newrotation; | 169 | int _newrotation; |
170 | 170 | ||
171 | QDataStream stream( data, IO_ReadOnly ); | 171 | QDataStream stream( data, IO_ReadOnly ); |
172 | odebug << "received system message: " << msg << oendl; | 172 | odebug << "received system message: " << msg << oendl; |
173 | if ( msg == "setCurrentRotation(int)" ) | 173 | if ( msg == "setCurrentRotation(int)" ) |
174 | { | 174 | { |
175 | stream >> _newrotation; | 175 | stream >> _newrotation; |
176 | odebug << "received setCurrentRotation(" << _newrotation << ")" << oendl; | 176 | odebug << "received setCurrentRotation(" << _newrotation << ")" << oendl; |
177 | 177 | ||
178 | switch ( _newrotation ) | 178 | switch ( _newrotation ) |
179 | { | 179 | { |
180 | case 270: preview->resize( QSize( 240, 288 ) ); break; | 180 | case 270: preview->resize( QSize( 240, 288 ) ); break; |
181 | case 180: preview->resize( QSize( 320, 208 ) ); break; | 181 | case 180: preview->resize( QSize( 320, 208 ) ); break; |
182 | default: QMessageBox::warning( this, "opie-camera", | 182 | default: QMessageBox::warning( this, "opie-camera", |
183 | "This rotation is not supported.\n" | 183 | "This rotation is not supported.\n" |
184 | "Supported are 180° and 270°" ); | 184 | "Supported are 180° and 270°" ); |
185 | } | 185 | } |
186 | 186 | ||
187 | if ( _newrotation != _rotation ) | 187 | if ( _newrotation != _rotation ) |
188 | { | 188 | { |
189 | int tmp = captureX; | 189 | int tmp = captureX; |
190 | captureX = captureY; | 190 | captureX = captureY; |
191 | captureY = tmp; | 191 | captureY = tmp; |
192 | _rotation = _newrotation; | 192 | _rotation = _newrotation; |
193 | } | 193 | } |
194 | 194 | ||
195 | updateCaption(); | 195 | updateCaption(); |
196 | 196 | ||
197 | } | 197 | } |
198 | } | 198 | } |
199 | 199 | ||
200 | 200 | ||
201 | void CameraMainWindow::changeZoom( int zoom ) | 201 | void CameraMainWindow::changeZoom( int zoom ) |
202 | { | 202 | { |
203 | int z; | 203 | int z; |
204 | switch ( zoom ) | 204 | switch ( zoom ) |
205 | { | 205 | { |
206 | case 0: z = 128; break; | 206 | case 0: z = 128; break; |
207 | case 1: z = 256; break; | 207 | case 1: z = 256; break; |
208 | case 2: z = 512; break; | 208 | case 2: z = 512; break; |
209 | default: assert( 0 ); break; | 209 | default: assert( 0 ); break; |
210 | } | 210 | } |
211 | 211 | ||
212 | ZCameraIO::instance()->setCaptureFrame( 240, 160, z ); | 212 | ZCameraIO::instance()->setCaptureFrame( 240, 160, z ); |
213 | } | 213 | } |
214 | 214 | ||
215 | 215 | ||
216 | void CameraMainWindow::showContextMenu() | 216 | void CameraMainWindow::showContextMenu() |
217 | { | 217 | { |
218 | QPopupMenu reso; | 218 | QPopupMenu reso; |
219 | reso.setCheckable( true ); | 219 | reso.setCheckable( true ); |
220 | resog->addTo( &reso ); | 220 | resog->addTo( &reso ); |
221 | 221 | ||
222 | QPopupMenu quality; | 222 | QPopupMenu quality; |
223 | quality.setCheckable( true ); | 223 | quality.setCheckable( true ); |
224 | qualityg->addTo( &quality ); | 224 | qualityg->addTo( &quality ); |
225 | 225 | ||
226 | QPopupMenu flip; | 226 | QPopupMenu flip; |
227 | flip.setCheckable( true ); | 227 | flip.setCheckable( true ); |
228 | flipg->addTo( &flip ); | 228 | flipg->addTo( &flip ); |
229 | 229 | ||
230 | QPopupMenu zoom; | 230 | QPopupMenu zoom; |
231 | zoom.setCheckable( true ); | 231 | zoom.setCheckable( true ); |
232 | zoomg->addTo( &zoom ); | 232 | zoomg->addTo( &zoom ); |
233 | 233 | ||
234 | QPopupMenu output; | 234 | QPopupMenu output; |
235 | output.setCheckable( true ); | 235 | output.setCheckable( true ); |
236 | outputg->addTo( &output ); | 236 | outputg->addTo( &output ); |
237 | 237 | ||
238 | QPopupMenu m( this ); | 238 | QPopupMenu m( this ); |
239 | m.insertItem( "&Resolution", &reso ); | 239 | m.insertItem( "&Resolution", &reso ); |
240 | m.insertItem( "&Zoom", &zoom ); | 240 | m.insertItem( "&Zoom", &zoom ); |
241 | m.insertItem( "&Flip", &flip ); | 241 | m.insertItem( "&Flip", &flip ); |
242 | m.insertItem( "&Quality", &quality ); | 242 | m.insertItem( "&Quality", &quality ); |
243 | m.insertItem( "&Output As", &output ); | 243 | m.insertItem( "&Output As", &output ); |
244 | 244 | ||
245 | #ifndef QT_NO_DEBUG | 245 | #ifndef QT_NO_DEBUG |
246 | m.insertItem( "&Debug!", this, SLOT( doSomething() ) ); | 246 | m.insertItem( "&Debug!", this, SLOT( doSomething() ) ); |
247 | #endif | 247 | #endif |
248 | 248 | ||
249 | m.exec( QCursor::pos() ); | 249 | m.exec( QCursor::pos() ); |
250 | } | 250 | } |
251 | 251 | ||
252 | 252 | ||
253 | void CameraMainWindow::resoMenuItemClicked( QAction* a ) | 253 | void CameraMainWindow::resoMenuItemClicked( QAction* a ) |
254 | { | 254 | { |
255 | switch ( _rotation ) | 255 | switch ( _rotation ) |
256 | { | 256 | { |
257 | case 270: | 257 | case 270: |
258 | captureY = a->text().left(3).toInt(); | 258 | captureY = a->text().left(3).toInt(); |
259 | captureX = a->text().right(3).toInt(); | 259 | captureX = a->text().right(3).toInt(); |
260 | break; | 260 | break; |
261 | case 180: | 261 | case 180: |
262 | captureX = a->text().left(3).toInt(); | 262 | captureX = a->text().left(3).toInt(); |
263 | captureY = a->text().right(3).toInt(); | 263 | captureY = a->text().right(3).toInt(); |
264 | break; | 264 | break; |
265 | default: QMessageBox::warning( this, "opie-camera", | 265 | default: QMessageBox::warning( this, "opie-camera", |
266 | "This rotation is not supported.\n" | 266 | "This rotation is not supported.\n" |
267 | "Supported are 180° and 270°" ); | 267 | "Supported are 180° and 270°" ); |
268 | } | 268 | } |
269 | odebug << "Capture Resolution now: " << captureX << ", " << captureY << oendl; | 269 | odebug << "Capture Resolution now: " << captureX << ", " << captureY << oendl; |
270 | updateCaption(); | 270 | updateCaption(); |
271 | } | 271 | } |
272 | 272 | ||
273 | 273 | ||
274 | void CameraMainWindow::qualityMenuItemClicked( QAction* a ) | 274 | void CameraMainWindow::qualityMenuItemClicked( QAction* a ) |
275 | { | 275 | { |
276 | quality = a->text().left(3).toInt(); | 276 | quality = a->text().left(3).toInt(); |
277 | odebug << "Quality now: " << quality << oendl; | 277 | odebug << "Quality now: " << quality << oendl; |
278 | updateCaption(); | 278 | updateCaption(); |
279 | } | 279 | } |
280 | 280 | ||
281 | 281 | ||
282 | void CameraMainWindow::zoomMenuItemClicked( QAction* a ) | 282 | void CameraMainWindow::zoomMenuItemClicked( QAction* a ) |
283 | { | 283 | { |
284 | zoom = QString( a->text().at(2) ).toInt(); | 284 | zoom = QString( a->text().at(2) ).toInt(); |
285 | odebug << "Zoom now: " << zoom << oendl; | 285 | odebug << "Zoom now: " << zoom << oendl; |
286 | ZCameraIO::instance()->setZoom( zoom ); | 286 | ZCameraIO::instance()->setZoom( zoom ); |
287 | updateCaption(); | 287 | updateCaption(); |
288 | } | 288 | } |
289 | 289 | ||
290 | 290 | ||
291 | void CameraMainWindow::flipMenuItemClicked( QAction* a ) | 291 | void CameraMainWindow::flipMenuItemClicked( QAction* a ) |
292 | { | 292 | { |
293 | flip = QString( a->text().at(0) ); | 293 | flip = QString( a->text().at(0) ); |
294 | odebug << "Flip now: " << flip << oendl; | 294 | odebug << "Flip now: " << flip << oendl; |
295 | if ( flip == "A" ) | 295 | if ( flip == "A" ) |
296 | ZCameraIO::instance()->setFlip( ZCameraIO::AUTOMATICFLIP ); | 296 | ZCameraIO::instance()->setFlip( ZCameraIO::AUTOMATICFLIP ); |
297 | else if ( flip == "0" ) | 297 | else if ( flip == "0" ) |
298 | ZCameraIO::instance()->setFlip( ZCameraIO::XNOFLIP | ZCameraIO::YNOFLIP ); | 298 | ZCameraIO::instance()->setFlip( ZCameraIO::XNOFLIP | ZCameraIO::YNOFLIP ); |
299 | else if ( flip == "X" ) | 299 | else if ( flip == "X" ) |
300 | ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP ); | 300 | ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP ); |
301 | else if ( flip == "Y" ) | 301 | else if ( flip == "Y" ) |
302 | ZCameraIO::instance()->setFlip( ZCameraIO::YFLIP ); | 302 | ZCameraIO::instance()->setFlip( ZCameraIO::YFLIP ); |
303 | else if ( flip == "*" ) | 303 | else if ( flip == "*" ) |
304 | ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP | ZCameraIO::YFLIP ); | 304 | ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP | ZCameraIO::YFLIP ); |
305 | 305 | ||
306 | updateCaption(); | 306 | updateCaption(); |
307 | } | 307 | } |
308 | 308 | ||
309 | 309 | ||
310 | void CameraMainWindow::outputMenuItemClicked( QAction* a ) | 310 | void CameraMainWindow::outputMenuItemClicked( QAction* a ) |
311 | { | 311 | { |
312 | captureFormat = a->text(); | 312 | captureFormat = a->text(); |
313 | odebug << "Output format now: " << captureFormat << oendl; | 313 | odebug << "Output format now: " << captureFormat << oendl; |
314 | updateCaption(); | 314 | updateCaption(); |
315 | } | 315 | } |
316 | 316 | ||
317 | 317 | ||
318 | void CameraMainWindow::shutterClicked() | 318 | void CameraMainWindow::shutterClicked() |
319 | { | 319 | { |
320 | if ( captureFormat != "AVI" ) // capture one photo per shutterClick | 320 | if ( captureFormat != "AVI" ) // capture one photo per shutterClick |
321 | { | 321 | { |
322 | Global::statusMessage( "CAPTURING..." ); | 322 | Global::statusMessage( "CAPTURING..." ); |
323 | qApp->processEvents(); | 323 | qApp->processEvents(); |
324 | 324 | ||
325 | odebug << "Shutter has been pressed" << oendl; | 325 | odebug << "Shutter has been pressed" << oendl; |
326 | ODevice::inst()->touchSound(); | 326 | ODevice::inst()->touchSound(); |
327 | 327 | ||
328 | performCapture( captureFormat ); | 328 | performCapture( captureFormat ); |
329 | } | 329 | } |
330 | else // capture video! start with one shutter click and stop with the next | 330 | else // capture video! start with one shutter click and stop with the next |
331 | { | 331 | { |
332 | !_capturing ? startVideoCapture() : stopVideoCapture(); | 332 | !_capturing ? startVideoCapture() : stopVideoCapture(); |
333 | } | 333 | } |
334 | } | 334 | } |
335 | 335 | ||
336 | 336 | ||
337 | void CameraMainWindow::performCapture( const QString& format ) | 337 | void CameraMainWindow::performCapture( const QString& format ) |
338 | { | 338 | { |
339 | QString name; | 339 | QString name; |
340 | name.sprintf( "/tmp/image-%d_%d_%d_q%d.%s", _pics++, captureX, captureY, quality, (const char*) captureFormat.lower() ); | 340 | name.sprintf( "/tmp/image-%d_%d_%d_q%d.%s", _pics++, captureX, captureY, quality, (const char*) captureFormat.lower() ); |
341 | QImage i; | 341 | QImage i; |
342 | ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, &i ); | 342 | ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, &i ); |
343 | QImage im = i.convertDepth( 32 ); | 343 | QImage im = i.convertDepth( 32 ); |
344 | bool result = im.save( name, format, quality ); | 344 | bool result = im.save( name, format, quality ); |
345 | if ( !result ) | 345 | if ( !result ) |
346 | { | 346 | { |
347 | oerr << "imageio-Problem while writing." << oendl; | 347 | oerr << "imageio-Problem while writing." << oendl; |
348 | Global::statusMessage( "Error!" ); | 348 | Global::statusMessage( "Error!" ); |
349 | } | 349 | } |
350 | else | 350 | else |
351 | { | 351 | { |
352 | odebug << captureFormat << "-image has been successfully captured" << oendl; | 352 | odebug << captureFormat << "-image has been successfully captured" << oendl; |
353 | Global::statusMessage( "Ok." ); | 353 | Global::statusMessage( "Ok." ); |
354 | } | 354 | } |
355 | } | 355 | } |
356 | 356 | ||
357 | 357 | ||
358 | void CameraMainWindow::startVideoCapture() | 358 | void CameraMainWindow::startVideoCapture() |
359 | { | 359 | { |
360 | //ODevice::inst()->touchSound(); | 360 | //ODevice::inst()->touchSound(); |
361 | ODevice::inst()->setLedState( Led_Mail, Led_BlinkSlow ); | 361 | ODevice::inst()->setLedState( Led_Mail, Led_BlinkSlow ); |
362 | 362 | ||
363 | _capturefd = ::open( CAPTUREFILE, O_WRONLY | O_CREAT | O_TRUNC ); | 363 | _capturefd = ::open( CAPTUREFILE, O_WRONLY | O_CREAT | O_TRUNC ); |
364 | if ( _capturefd == -1 ) | 364 | if ( _capturefd == -1 ) |
365 | { | 365 | { |
366 | owarn << "can't open capture file: " << strerror(errno) << oendl; | 366 | owarn << "can't open capture file: " << strerror(errno) << oendl; |
367 | return; | 367 | return; |
368 | } | 368 | } |
369 | 369 | ||
370 | _capturebuf = new unsigned char[captureX*captureY*2]; | 370 | _capturebuf = new unsigned char[captureX*captureY*2]; |
371 | _capturing = true; | 371 | _capturing = true; |
372 | _videopics = 0; | 372 | _videopics = 0; |
373 | _framerate = 0; | 373 | _framerate = 0; |
374 | updateCaption(); | 374 | updateCaption(); |
375 | _time.start(); | 375 | _time.start(); |
376 | preview->setRefreshingRate( 1000 ); | 376 | preview->setRefreshingRate( 1000 ); |
377 | startTimer( 100 ); // too fast but that is ok | 377 | startTimer( 100 ); // too fast but that is ok |
378 | } | 378 | } |
379 | 379 | ||
380 | 380 | ||
381 | void CameraMainWindow::timerEvent( QTimerEvent* ) | 381 | void CameraMainWindow::timerEvent( QTimerEvent* ) |
382 | { | 382 | { |
383 | if ( !_capturing ) | 383 | if ( !_capturing ) |
384 | { | 384 | { |
385 | odebug << "timer event in CameraMainWindow without capturing video ?" << oendl; | 385 | odebug << "timer event in CameraMainWindow without capturing video ?" << oendl; |
386 | return; | 386 | return; |
387 | } | 387 | } |
388 | 388 | ||
389 | odebug << "timer event during video - now capturing frame #" << _videopics+1 << oendl; | 389 | odebug << "timer event during video - now capturing frame #" << _videopics+1 << oendl; |
390 | 390 | ||
391 | ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, _capturebuf ); | 391 | ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, _capturebuf ); |
392 | _videopics++; | 392 | _videopics++; |
393 | ::write( _capturefd, _capturebuf, captureX*captureY*2 ); | 393 | ::write( _capturefd, _capturebuf, captureX*captureY*2 ); |
394 | setCaption( QString().sprintf( "Capturing %dx%d @ %.2f fps %d", | 394 | setCaption( QString().sprintf( "Capturing %dx%d @ %.2f fps %d", |
395 | captureX, captureY, 1000.0 / (_time.elapsed()/_videopics), _videopics ) ); | 395 | captureX, captureY, 1000.0 / (_time.elapsed()/_videopics), _videopics ) ); |
396 | } | 396 | } |
397 | 397 | ||
398 | 398 | ||
399 | void CameraMainWindow::stopVideoCapture() | 399 | void CameraMainWindow::stopVideoCapture() |
400 | { | 400 | { |
401 | killTimers(); | 401 | killTimers(); |
402 | //ODevice::inst()->touchSound(); | 402 | //ODevice::inst()->touchSound(); |
403 | ODevice::inst()->setLedState( Led_Mail, Led_Off ); | 403 | ODevice::inst()->setLedState( Led_Mail, Led_Off ); |
404 | _capturing = false; | 404 | _capturing = false; |
405 | updateCaption(); | 405 | updateCaption(); |
406 | ::close( _capturefd ); | 406 | ::close( _capturefd ); |
407 | _framerate = 1000.0 / (_time.elapsed()/_videopics); | 407 | _framerate = 1000.0 / (_time.elapsed()/_videopics); |
408 | 408 | ||
409 | postProcessVideo( CAPTUREFILE, QString().sprintf( "/tmp/video-%d_%d_%d_q%d-%dfps.avi", _videos++, captureX, captureY, quality, _framerate ) ); | 409 | postProcessVideo( CAPTUREFILE, QString().sprintf( "/tmp/video-%d_%d_%d_q%d-%dfps.avi", _videos++, captureX, captureY, quality, _framerate ) ); |
410 | 410 | ||
411 | #ifndef QT_NO_DEBUG | 411 | #ifndef QT_NO_DEBUG |
412 | preview->setRefreshingRate( 1500 ); | 412 | preview->setRefreshingRate( 1500 ); |
413 | #else | 413 | #else |
414 | preview->setRefreshingRate( 200 ); | 414 | preview->setRefreshingRate( 200 ); |
415 | #endif | 415 | #endif |
416 | 416 | ||
417 | //delete[] _capturebuf; //FIXME: close memory leak | 417 | //delete[] _capturebuf; //FIXME: close memory leak |
418 | } | 418 | } |
419 | 419 | ||
420 | void CameraMainWindow::postProcessVideo( const QString& infile, const QString& outfile ) | 420 | void CameraMainWindow::postProcessVideo( const QString& infile, const QString& outfile ) |
421 | { | 421 | { |
422 | preview->setRefreshingRate( 0 ); | 422 | preview->setRefreshingRate( 0 ); |
423 | 423 | ||
424 | /* | 424 | /* |
425 | unsigned char buf[153600]; | 425 | unsigned char buf[153600]; |
426 | 426 | ||
427 | int fd = ::open( "/var/compile/opie/noncore/multimedia/camera/capture-320x240.dat", O_RDONLY ); | 427 | int fd = ::open( "/var/compile/opie/noncore/multimedia/camera/capture-320x240.dat", O_RDONLY ); |
428 | ::read( fd, &buf, 153600 ); | 428 | ::read( fd, &buf, 153600 ); |
429 | QImage i; | 429 | QImage i; |
430 | bufferToImage( 240, 320, (unsigned char*) &buf, &i ); | 430 | bufferToImage( 240, 320, (unsigned char*) &buf, &i ); |
431 | QPixmap p; | 431 | QPixmap p; |
432 | p.convertFromImage( i ); | 432 | p.convertFromImage( i ); |
433 | preview->setPixmap( p ); | 433 | preview->setPixmap( p ); |
434 | imageToFile( &i, "/tmp/tmpfile", "JPEG", 100 ); | 434 | imageToFile( &i, "/tmp/tmpfile", "JPEG", 100 ); |
435 | return; | 435 | return; |
436 | */ | 436 | */ |
437 | 437 | ||
438 | QDialog* fr = new QDialog( this, "splash", false, QWidget::WStyle_StaysOnTop ); //, false, QWidget::WStyle_NoBorder | QWidget::WStyle_Customize ); | 438 | QDialog* fr = new QDialog( this, "splash", false, QWidget::WStyle_StaysOnTop ); //, false, QWidget::WStyle_NoBorder | QWidget::WStyle_Customize ); |
439 | fr->setCaption( "Please wait..." ); | 439 | fr->setCaption( "Please wait..." ); |
440 | QVBoxLayout* box = new QVBoxLayout( fr, 2, 2 ); | 440 | QVBoxLayout* box = new QVBoxLayout( fr, 2, 2 ); |
441 | QProgressBar* bar = new QProgressBar( fr ); | 441 | QProgressBar* bar = new QProgressBar( fr ); |
442 | bar->setCenterIndicator( true ); | 442 | bar->setCenterIndicator( true ); |
443 | bar->setTotalSteps( _videopics-1 ); | 443 | bar->setTotalSteps( _videopics-1 ); |
444 | QLabel* label = new QLabel( "Post processing frame bla/bla", fr ); | 444 | QLabel* label = new QLabel( "Post processing frame bla/bla", fr ); |
445 | box->addWidget( bar ); | 445 | box->addWidget( bar ); |
446 | box->addWidget( label ); | 446 | box->addWidget( label ); |
447 | fr->show(); | 447 | fr->show(); |
448 | label->show(); | 448 | label->show(); |
449 | bar->show(); | 449 | bar->show(); |
450 | fr->repaint(); | 450 | fr->repaint(); |
451 | qApp->processEvents(); | 451 | qApp->processEvents(); |
452 | 452 | ||
453 | // open files | 453 | // open files |
454 | 454 | ||
455 | int infd = ::open( (const char*) infile, O_RDONLY ); | 455 | int infd = ::open( (const char*) infile, O_RDONLY ); |
456 | if ( infd == -1 ) | 456 | if ( infd == -1 ) |
457 | { | 457 | { |
458 | owarn << "couldn't open capture file: " << strerror(errno) << oendl; | 458 | owarn << "couldn't open capture file: " << strerror(errno) << oendl; |
459 | return; | 459 | return; |
460 | } | 460 | } |
461 | 461 | ||
462 | int outfd = ::open( (const char*) outfile, O_CREAT | O_WRONLY | O_TRUNC, 0644 ); | 462 | int outfd = ::open( (const char*) outfile, O_CREAT | O_WRONLY | O_TRUNC, 0644 ); |
463 | if ( outfd == -1 ) | 463 | if ( outfd == -1 ) |
464 | { | 464 | { |
465 | owarn << "couldn't open output file: " << strerror(errno) << oendl; | 465 | owarn << "couldn't open output file: " << strerror(errno) << oendl; |
466 | return; | 466 | return; |
467 | } | 467 | } |
468 | 468 | ||
469 | int framesize = captureX*captureY*2; | 469 | int framesize = captureX*captureY*2; |
470 | 470 | ||
471 | unsigned char* inbuffer = new unsigned char[ framesize ]; | 471 | unsigned char* inbuffer = new unsigned char[ framesize ]; |
472 | QImage image; | 472 | QImage image; |
473 | 473 | ||
474 | avi_start( outfd, _videopics ); // write preambel | 474 | avi_start( outfd, _videopics ); // write preambel |
475 | 475 | ||
476 | // post process | 476 | // post process |
477 | 477 | ||
478 | for ( int i = 0; i < _videopics; ++i ) | 478 | for ( int i = 0; i < _videopics; ++i ) |
479 | { | 479 | { |
480 | odebug << "processing frame " << i << oendl; | 480 | odebug << "processing frame " << i << oendl; |
481 | 481 | ||
482 | // <gui> | 482 | // <gui> |
483 | label->setText( QString().sprintf( "Post processing frame %d / %d", i+1, _videopics ) ); | 483 | label->setText( QString().sprintf( "Post processing frame %d / %d", i+1, _videopics ) ); |
484 | bar->setProgress( i ); | 484 | bar->setProgress( i ); |
485 | bar->repaint(); | 485 | bar->repaint(); |
486 | qApp->processEvents(); | 486 | qApp->processEvents(); |
487 | // </gui> | 487 | // </gui> |
488 | 488 | ||
489 | int read = ::read( infd, inbuffer, framesize ); | 489 | int read = ::read( infd, inbuffer, framesize ); |
490 | odebug << "read " << read << " bytes" << oendl; | 490 | odebug << "read " << read << " bytes" << oendl; |
491 | bufferToImage( captureX, captureY, inbuffer, &image ); | 491 | bufferToImage( captureX, captureY, inbuffer, &image ); |
492 | 492 | ||
493 | QPixmap p; | 493 | QPixmap p; |
494 | p.convertFromImage( image ); | 494 | p.convertFromImage( image ); |
495 | preview->setPixmap( p ); | 495 | preview->setPixmap( p ); |
496 | preview->repaint(); | 496 | preview->repaint(); |
497 | qApp->processEvents(); | 497 | qApp->processEvents(); |
498 | 498 | ||
499 | #ifndef QT_NO_DEBUG | ||
500 | QString tmpfilename; | ||
501 | tmpfilename.sprintf( "/tmp/test/%04d.jpg", i ); | ||
502 | #else | ||
499 | QString tmpfilename( "/tmp/tempfile" ); | 503 | QString tmpfilename( "/tmp/tempfile" ); |
500 | //tmpfilename.sprintf( "/tmp/test/%d.jpg", i ); | 504 | #endif |
501 | 505 | ||
502 | imageToFile( &image, tmpfilename, "JPEG", quality ); | 506 | imageToFile( &image, tmpfilename, "JPEG", quality ); |
503 | 507 | ||
504 | QFile framefile( tmpfilename ); | 508 | QFile framefile( tmpfilename ); |
505 | if ( !framefile.open( IO_ReadOnly ) ) | 509 | if ( !framefile.open( IO_ReadOnly ) ) |
506 | { | 510 | { |
507 | oerr << "can't process file: %s" << strerror(errno) << oendl; | 511 | oerr << "can't process file: %s" << strerror(errno) << oendl; |
508 | return; // TODO: clean up temp ressources | 512 | return; // TODO: clean up temp ressources |
509 | } | 513 | } |
510 | 514 | ||
511 | int filesize = framefile.size(); | 515 | int filesize = framefile.size(); |
512 | odebug << "filesize for frame " << i << " = " << filesize << oendl; | 516 | odebug << "filesize for frame " << i << " = " << filesize << oendl; |
513 | 517 | ||
514 | unsigned char* tempbuffer = new unsigned char[ filesize ]; | 518 | unsigned char* tempbuffer = new unsigned char[ filesize ]; |
515 | framefile.readBlock( (char*) tempbuffer, filesize ); | 519 | framefile.readBlock( (char*) tempbuffer, filesize ); |
516 | avi_add( outfd, tempbuffer, filesize ); | 520 | avi_add( outfd, tempbuffer, filesize ); |
517 | delete tempbuffer; | 521 | delete tempbuffer; |
518 | framefile.close(); | 522 | framefile.close(); |
519 | } | 523 | } |
520 | 524 | ||
521 | avi_end( outfd, captureX, captureY, _framerate ); | 525 | avi_end( outfd, captureX, captureY, _framerate ); |
522 | 526 | ||
523 | fr->hide(); | 527 | fr->hide(); |
524 | delete fr; | 528 | delete fr; |
525 | 529 | ||
526 | updateCaption(); | 530 | updateCaption(); |
527 | 531 | ||
528 | } | 532 | } |
529 | 533 | ||
530 | 534 | ||
531 | void CameraMainWindow::updateCaption() | 535 | void CameraMainWindow::updateCaption() |
532 | { | 536 | { |
533 | if ( !_capturing ) | 537 | if ( !_capturing ) |
534 | setCaption( QString().sprintf( "Opie-Camera: %dx%d %s q%d z%d (%s)", captureX, captureY, (const char*) captureFormat.lower(), quality, zoom, (const char*) flip ) ); | 538 | setCaption( QString().sprintf( "Opie-Camera: %dx%d %s q%d z%d (%s)", captureX, captureY, (const char*) captureFormat.lower(), quality, zoom, (const char*) flip ) ); |
535 | else | 539 | else |
536 | setCaption( "Opie-Camera: => CAPTURING <=" ); | 540 | setCaption( "Opie-Camera: => CAPTURING <=" ); |
537 | } | 541 | } |
538 | 542 | ||
539 | 543 | ||
540 | #ifndef QT_NO_DEBUG | 544 | #ifndef QT_NO_DEBUG |
541 | void CameraMainWindow::doSomething() | 545 | void CameraMainWindow::doSomething() |
542 | { | 546 | { |
543 | captureX = 240; | 547 | captureX = 240; |
544 | captureY = 320; | 548 | captureY = 320; |
545 | _videopics = 176; | 549 | _videopics = 50; |
546 | _framerate = 5; | 550 | _framerate = 5; |
547 | postProcessVideo( "/var/compile/opie/noncore/multimedia/camera/capture-320x240.dat", | 551 | postProcessVideo( "/var/compile/opie/noncore/multimedia/camera/capture.dat", |
548 | "/tmp/output.avi" ); | 552 | "/tmp/output.avi" ); |
549 | } | 553 | } |
550 | #endif | 554 | #endif |
551 | 555 | ||