00001 #if 0
00002 #ifdef __linux__
00003
00004 #include "CameraDriverV4L1.h"
00005 #include "Shared/debuget.h"
00006
00007 #include "Shared/MarkScope.h"
00008
00009 #include <fcntl.h>
00010 #include <sys/ioctl.h>
00011
00012 using namespace std;
00013
00014 const std::string CameraDriverV4L1::autoRegisterCameraDriverV4L1 = DeviceDriver::getRegistry().registerType<CameraDriverV4L1>("CameraV4L1");
00015 const size_t CameraDriverV4L1::HEADER_SIZE = LoadSave::getSerializedSize<unsigned int>()*4;
00016
00017 unsigned int CameraDriverV4L1::getData(const char *& payload, unsigned int& payloadSize, unsigned int& timestamp, std::string& name) {
00018
00019 payload=NULL;
00020 payloadSize=0;
00021 if(camfd<0)
00022 return frameCount;
00023
00024 curBuf.resize(getBufferSize());
00025
00026
00027
00028 if(blocking) {
00029 if( fcntl(camfd,F_SETFL,O_NONBLOCK) != 0) {
00030 perror("ioctl set non-blocking mode");
00031 blocking = fcntl(camfd,F_GETFL) & O_NONBLOCK;
00032 } else
00033 blocking=false;
00034 }
00035
00036 unsigned int t=get_time();
00037 unsigned int dropped=0;
00038 int nbytes;
00039 size_t lastread;
00040 while(timestamp>t) {
00041
00042 while( (nbytes=read(camfd, &curBuf[HEADER_SIZE], curBuf.size()-HEADER_SIZE)) >= 0) {
00043 lastread=nbytes;
00044 ++dropped;
00045
00046 }
00047 usleep(static_cast<unsigned int>((timestamp-t)*1000/(getTimeScale()>0?getTimeScale():1.f)));
00048 t=get_time();
00049 }
00050 timestamp = t;
00051
00052 if(camfd<0)
00053 return frameCount;
00054
00055 unsigned int width, height, components=3;
00056 {
00057 MarkScope l(lock);
00058 width=getWidth();
00059 height=getHeight();
00060 if(curBuf.size()!=getBufferSize()) {
00061 curBuf.resize(getBufferSize());
00062 dropped=0;
00063 }
00064 }
00065
00066
00067 while( (nbytes=read(camfd, &curBuf[HEADER_SIZE], curBuf.size()-HEADER_SIZE)) >= 0) {
00068 lastread=nbytes;
00069 ++dropped;
00070
00071 }
00072 timestamp = get_time();
00073
00074 char * buf=reinterpret_cast<char*>(&curBuf[0]);
00075 unsigned int remain=curBuf.size();
00076 LoadSave::encodeIncT(*layer,buf,remain);
00077 LoadSave::encodeIncT(width,buf,remain);
00078 LoadSave::encodeIncT(height,buf,remain);
00079 LoadSave::encodeIncT(components,buf,remain);
00080
00081 if(remain<img_size) {
00082
00083
00084 return frameCount;
00085 }
00086 if(dropped==0 || lastread!=img_size) {
00087 ASSERTRETVAL(static_cast<size_t>(remain)>=img_size, "Read more than remains in buffer!", frameCount);
00088
00089 if( fcntl(camfd,F_SETFL,0) != 0) {
00090 perror("ioctl set blocking mode");
00091 blocking = fcntl(camfd,F_GETFL) & O_NONBLOCK;
00092 } else
00093 blocking=true;
00094
00095
00096 nbytes = read(camfd, buf, remain);
00097 timestamp = get_time();
00098
00099 if( fcntl(camfd,F_SETFL,O_NONBLOCK) != 0) {
00100 perror("ioctl set non-blocking mode");
00101 blocking = fcntl(camfd,F_GETFL) & O_NONBLOCK;
00102 } else
00103 blocking=false;
00104 if ( nbytes<0 ) {
00105 perror("Error reading from camera");
00106 return frameCount;
00107 }
00108 lastread=nbytes;
00109 ++dropped;
00110 }
00111
00112 MarkScope l(lock);
00113
00114 if ( lastread!=img_size
00115 || (resolution!=0 && img_size!=width*height*6)
00116 || (resolution==0 && img_size!=width*height*3/2)
00117 )
00118 {
00119
00120
00121
00122
00123 return frameCount;
00124 }
00125
00126 if(resolution==0)
00127 interleave_yuv_up();
00128 else
00129 interleave_yuv_down();
00130
00131 if ( autobright )
00132 auto_bright();
00133
00134 curBuf.swap(lastBuf);
00135 payload = reinterpret_cast<char*>(&lastBuf[0]);
00136 payloadSize = lastBuf.size();
00137 name = nextName();
00138 return frameCount+=dropped;
00139 }
00140
00141
00142 void CameraDriverV4L1::setDataSourceThread(LoadDataThread* th) {
00143 DataSource::setDataSourceThread(th);
00144 if(th != NULL) {
00145 open_cam();
00146 path.addPrimitiveListener(this);
00147 resolution.addPrimitiveListener(this);
00148 } else {
00149 resolution.removePrimitiveListener(this);
00150 path.removePrimitiveListener(this);
00151 close_cam();
00152 }
00153 }
00154
00155 void CameraDriverV4L1::plistValueChanged(const plist::PrimitiveBase& pl) {
00156 if(&pl == &path) {
00157 MarkScope l(lock);
00158 open_cam();
00159 } else if(&pl == &resolution) {
00160 MarkScope l(lock);
00161 set_resolution();
00162 }
00163 }
00164
00165 void CameraDriverV4L1::close_cam() {
00166 if(camfd >= 0) {
00167 ::close(camfd);
00168 camfd=-1;
00169 }
00170 }
00171
00172 void CameraDriverV4L1::open_cam() {
00173 close_cam();
00174 if(path.size() == 0)
00175 return;
00176
00177 camfd = ::open(path.c_str(), O_RDWR|O_NONBLOCK, 0);
00178 if ( camfd < 0 ) {
00179 perror("Error on open()");
00180 cerr << "Could not open camera device '" << path << "'" << endl;
00181 return;
00182 }
00183 blocking=false;
00184
00185 set_resolution();
00186
00187 if ( ioctl(camfd, VIDIOCGPICT, &vid_pic) == -1 )
00188 perror ("ioctl (VIDIOCGPICT) brightness");
00189 vid_pic.brightness=128*256;
00190 if ( ioctl(camfd, VIDIOCSPICT, &vid_pic) == -1 )
00191 perror ("ioctl (VIDIOCSPICT) brightness");
00192
00193
00194
00195 isYUVMode=false;
00196 ioctl(camfd, VIDIOCGPICT, &vid_pic);
00197 vid_pic.depth=16;
00198 vid_pic.palette=VIDEO_PALETTE_YUV420P;
00199 if ( ioctl(camfd, VIDIOCSPICT, &vid_pic) == -1 )
00200 perror ("ioctl (VIDIOCSPICT) palette");
00201 else {
00202 img_size = vid_win.width * vid_win.height + vid_win.width*vid_win.height/2;
00203 isYUVMode=true;
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213 }
00214
00215 void CameraDriverV4L1::get_cam_info() {
00216 ioctl(camfd, VIDIOCGCAP, &vid_caps);
00217 ioctl(camfd, VIDIOCGWIN, &vid_win);
00218 ioctl(camfd, VIDIOCGPICT, &vid_pic);
00219 }
00220
00221 void CameraDriverV4L1::set_cam_info() {
00222 if ( ioctl(camfd, VIDIOCSPICT, &vid_pic) == -1 ) {
00223 perror ("ioctl (VIDIOCSPICT)");
00224 cout << "refreshing settings..." << endl;
00225 if ( ioctl(camfd, VIDIOCGPICT, &vid_pic) == -1 )
00226 perror ("ioctl (VIDIOCGPICT)");
00227 }
00228 if ( ioctl(camfd, VIDIOCSWIN, &vid_win) == -1 ) {
00229 perror ("ioctl (VIDIOCSWIN)");
00230 cout << "refreshing settings..." << endl;
00231 if ( ioctl(camfd, VIDIOCGWIN, &vid_win) == -1 )
00232 perror ("ioctl (VIDIOCGWIN)");
00233 }
00234 }
00235
00236 void CameraDriverV4L1::set_resolution() {
00237 get_cam_info();
00238 int width = vid_caps.maxwidth >> (resolution==0 ? 0 : resolution-1);
00239 int height = vid_caps.maxheight >> (resolution==0 ? 0 : resolution-1);
00240 if ( width < vid_caps.minwidth || height < vid_caps.minheight ) {
00241 cout << "Warning: requested image " << width<<'x'<<height<<" smaller than camera's minimum size, trying ";
00242 width = vid_caps.minwidth;
00243 height = vid_caps.minheight;
00244 cout << width<<'x'<<height << endl;
00245 }
00246
00247 vid_win.width = width;
00248 vid_win.height = height;
00249 set_cam_info();
00250 width = vid_win.width;
00251 height = vid_win.height;
00252
00253 if(isYUVMode) {
00254 img_size = width * height + width * height / 2;
00255 } else {
00256 img_size = width * height * 3;
00257 }
00258
00259 cout << "Camera image size is " << getWidth() << 'x' << getHeight() << endl;
00260 }
00261
00262
00263
00264 void CameraDriverV4L1::auto_bright() {
00265 size_t total = 0;
00266 unsigned char *pix = &curBuf[HEADER_SIZE];
00267 const size_t skip = getWidth() * getHeight() / 719;
00268 const size_t npix = getWidth() * getHeight() / skip;
00269 const unsigned char *endp = pix + npix*skip*3;
00270 for (; pix!=endp; pix+=skip*3)
00271 total += *pix;
00272 int average = total / npix;
00273 if((average <= 120 || average >= 136)) {
00274 int bright = vid_pic.brightness + (128 - average)*256/4;
00275 const typeof(vid_pic.brightness) maxBright = numeric_limits<typeof(vid_pic.brightness)>::max();
00276 const typeof(vid_pic.brightness) minBright = numeric_limits<typeof(vid_pic.brightness)>::min();
00277 if(bright>maxBright)
00278 vid_pic.brightness = maxBright;
00279 else if(bright<minBright)
00280 vid_pic.brightness = minBright;
00281 else
00282 vid_pic.brightness = bright;
00283
00284 set_cam_info();
00285 }
00286 }
00287
00288 void CameraDriverV4L1::interleave_yuv_down() {
00289 unsigned char * buffer = &curBuf[HEADER_SIZE];
00290 int width = vid_win.width;
00291 int height = vid_win.height;
00292
00293
00294 char tmp[width/2];
00295 int x,y=0;
00296 for(x=0; x<width; x+=2) {
00297 short t=buffer[x+y*width];
00298 t+=buffer[x+y*width+1];
00299 t+=buffer[x+y*width+width];
00300 t+=buffer[x+y*width+width+1];
00301 tmp[x/2] = t/4;
00302 }
00303 for(x=0; x<width/2; x++) {
00304 buffer[x*3] = tmp[x];
00305 }
00306 for(y=2; y<height; y+=2) {
00307 for(x=0; x<width; x+=2) {
00308 short t=buffer[x+y*width];
00309 t+=buffer[x+y*width+1];
00310 t+=buffer[x+y*width+width];
00311 t+=buffer[x+y*width+width+1];
00312 buffer[y*width/4*3+x/2*3] = t/4;
00313 }
00314 }
00315
00316 unsigned char * c = &buffer[width*height];
00317 buffer = &curBuf[HEADER_SIZE]+1;
00318 unsigned char * endp = buffer + width*height/4*3;
00319 while(buffer!=endp) {
00320 *buffer = *c++;
00321 buffer+=3;
00322 }
00323 buffer = &curBuf[HEADER_SIZE]+2;
00324 endp = buffer + width*height/4*3;
00325 while(buffer!=endp) {
00326 *buffer = *c++;
00327 buffer+=3;
00328 }
00329 }
00330
00331 void CameraDriverV4L1::interleave_yuv_up() {
00332 unsigned char * buffer = &curBuf[HEADER_SIZE];
00333 size_t width = vid_win.width;
00334 size_t height = vid_win.height;
00335 tmpBuf.resize(getBufferSize());
00336 memcpy(&tmpBuf[0],&curBuf[0],HEADER_SIZE);
00337 unsigned char * out = &tmpBuf[HEADER_SIZE];
00338
00339
00340 unsigned char * i = buffer;
00341 unsigned char * o = out;
00342 unsigned char * e = i + width*height;
00343 while(i!=e) {
00344 *o=*i++;
00345 o+=3;
00346 }
00347
00348
00349 o = out+1;
00350 buffer+=width*height;
00351 for(size_t y=0; y<height/2; ++y) {
00352 i = buffer+width/2*y;
00353 e = i + width/2;
00354 while(i!=e) {
00355 *o=*(o+3)=*(o+width*3)=*(o+width*3+3)=*i++;
00356 o+=6;
00357 }
00358 o+=width*3;
00359 }
00360
00361
00362 o = out+2;
00363 buffer+=width*height/4;
00364 for(size_t y=0; y<height/2; ++y) {
00365 i = buffer+width/2*y;
00366 e = i + width/2;
00367 while(i!=e) {
00368 *o=*(o+3)=*(o+width*3)=*(o+width*3+3)=*i++;
00369 o+=6;
00370 }
00371 o+=width*3;
00372 }
00373
00374 curBuf.swap(tmpBuf);
00375 }
00376
00377
00378
00379
00380
00381
00382
00383 #endif
00384 #endif