00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "Video4Linux1.h"
00037 #include <core/FileSystem.h>
00038 #include <core/Utilities.h>
00039
00040 #include <fcntl.h>
00041 #include <sys/ioctl.h>
00042
00043
00044
00045
00046
00047
00048
00049
00050 using namespace std;
00051 using namespace wosh;
00052
00053
00054
00055
00056 Video4Linux1::Video4Linux1( BundleGeneric& bundle )
00057 : Video4LinuxImpl(bundle) {
00058 this->fd = -1;
00059 this->videoBuffer = NULL;
00060 this->videoBufferSize = 0;
00061
00062 this->src_depth = 0;
00063
00064 memset(&this->cap, 0, sizeof(this->cap));
00065 memset(&this->win, 0, sizeof(this->win));
00066 memset(&this->vpic, 0, sizeof(this->vpic));
00067
00068
00069 }
00070
00071 Video4Linux1::~Video4Linux1() {
00072 Log(LOG_VERBOSE, ":~Video4Linux1(): Destroying.." );
00073 if ( isThreadRunning() )
00074 quitThread(20000);
00075
00076 if ( this->videoBuffer != NULL )
00077 delete [] videoBuffer; this->videoBuffer = NULL;
00078 }
00079
00080
00081
00082
00083
00084 bool Video4Linux1::initializingThread() {
00085 if ( this->fd < 0 ) return false;
00086 return true;
00087 }
00088
00089 void Video4Linux1::runThread() {
00090 Log(LOG_VERBOSE, ":runThread(): Loop Starting.." );
00091
00092 if ( this->videoListener != NULL )
00093 this->videoListener->video_device_connection( 1, this );
00094
00095 while(this->running) {
00096 setThreadAlive();
00097 if ( !this->streaming ) {
00098 ThreadImpl::sleepForMSec( 500 );
00099 }
00100 if ( this->rate != 0 )
00101 Thread::sleepWhile( this,this->rate, 50, &this->running );
00102
00103 switch(this->vpic.palette) {
00104 case VIDEO_PALETTE_RGB24:
00105 if ( this->videoListener != NULL )
00106 this->videoListener->video_frame_available( this );
00107 break;
00108 case VIDEO_PALETTE_RGB565:
00109 case VIDEO_PALETTE_RGB555:
00110 default:
00111 break;
00112 }
00113 }
00114
00115 Log(LOG_VERBOSE, ":runThread(): Loop Stopped" );
00116 }
00117
00118 void Video4Linux1::exitingThread() {
00119
00120 if ( this->videoListener != NULL )
00121 this->videoListener->video_device_connection( 0, this );
00122
00123 Log(LOG_INFO, ":disconnect() : Closing input device.." );
00124 close(this->fd);
00125 this->fd = -1;
00126
00127 }
00128
00129
00130
00131
00132
00133
00134 WRESULT Video4Linux1::connectDevice( const std::string& device, unsigned long timeout ) {
00135 if ( this->fd != -1 || isThreadRunning() ) {
00136 Log(LOG_CRITICAL, ":connect(%s) FAILED : device already opened!", device.c_str() );
00137 return WRET_ERR_ILLEGAL_USE;
00138 }
00139
00140 this->fd = open( device.c_str(), O_RDONLY );
00141 if ( this->fd < 0 ) {
00142 Log(LOG_CRITICAL, ":connect(%s) FAILED opening device", device.c_str() );
00143 return WRET_ERR_INTERNAL;
00144 }
00145
00146 if ( ioctl(this->fd,VIDIOCGCAP, &this->cap) < 0 ) {
00147 Log(LOG_CRITICAL, ":connect(%s) FAILED opening device (not VIDEOGCAP device)", device.c_str() );
00148 close(this->fd);
00149 this->fd = -1;
00150 return WRET_ERR_INTERNAL;
00151 }
00152
00153 if ( ioctl(this->fd,VIDIOCGWIN, &this->win) < 0 ) {
00154 Log(LOG_CRITICAL, ":connect(%s) FAILED getting video overlay window (VIDIOCGWIN)", device.c_str() );
00155 close(this->fd);
00156 this->fd = -1;
00157 return WRET_ERR_INTERNAL;
00158 }
00159 WRESULT ret_res = setupResolution();
00160 if ( WFAILED(ret_res) ) {
00161 Log(LOG_CRITICAL, ":connect(%s) FAILED#%d setupResolution()", device.c_str(), ret_res );
00162 close(this->fd);
00163 this->fd = -1;
00164 return WRET_ERR_INTERNAL;
00165 }
00166 this->videoDevice = device;
00167 Log(LOG_VERBOSE, ":connect(%s,%d) : Starting Thread..", device.c_str(), timeout );
00168 WRESULT ret_thread = startThread(timeout);
00169 if ( WFAILED(ret_thread) )
00170 Log(LOG_CRITICAL, ":connect(%s) FAILED#%d starting thread()", device.c_str(), ret_thread );
00171 return ret_thread;
00172 }
00173
00174 WRESULT Video4Linux1::disconnectDevice( unsigned long timeout ) {
00175 if ( this->fd == -1 || !isThreadRunning() ) {
00176 Log(LOG_CRITICAL, ":disconnect() FAILED : device not opened!" );
00177 return WRET_ERR_ILLEGAL_USE;
00178 }
00179 WRESULT ret = quitThread(timeout);
00180 if ( WFAILED(ret) ) {
00181 Log(LOG_CRITICAL, ":disconnect(%d) FAILED#%d [TimedOut]!", timeout, ret );
00182 }
00183 return ret;
00184 }
00185
00186
00187
00188
00189 WRESULT Video4Linux1::setupResolution() {
00190 if ( this->fd == -1 ) {
00191 Log(LOG_CRITICAL, ":setupResolution() FAILED : device not opened!" );
00192 return WRET_ERR_ILLEGAL_USE;
00193 }
00194 Log(LOG_VERBOSE, ":setupResolution() : Setting up resolution.." );
00195
00196 if ( ioctl(this->fd,VIDIOCGPICT, &this->vpic) < 0 ) {
00197 Log(LOG_CRITICAL, ":setupResolution() FAILED getting picture properties (VIDIOCGPICT)" );
00198 return WRET_ERR_INTERNAL;
00199 }
00200
00201 if ( this->cap.type & VID_TYPE_MONOCHROME ) {
00202 this->vpic.depth = 8;
00203 this->vpic.palette = VIDEO_PALETTE_GREY;
00204 if( ioctl(this->fd,VIDIOCSPICT, &this->vpic) < 0 ) {
00205 Log(LOG_VERBOSE, ":setupResolution() GREY:8 not supported. Trying GREY:6 .." );
00206 this->vpic.depth = 6;
00207 if( ioctl(this->fd,VIDIOCSPICT, &this->vpic) < 0 ) {
00208 Log(LOG_VERBOSE, ":setupResolution() GREY:6 not supported. Trying GREY:4 .." );
00209 this->vpic.depth = 4;
00210 if ( ioctl(this->fd,VIDIOCSPICT, &this->vpic) < 0 ) {
00211 Log(LOG_CRITICAL, ":setupResolution() FAILED : Unable to find a supported Capture format" );
00212 return WRET_ERR_INTERNAL;
00213 }
00214 }
00215 }
00216 Log(LOG_INFO, ":setupResolution() : Resolution: GREY / %d bpp", this->vpic.depth );
00217 }
00218 else {
00219 this->vpic.depth = 24;
00220 this->vpic.palette = VIDEO_PALETTE_RGB24;
00221 if ( ioctl(this->fd,VIDIOCSPICT, &this->vpic) < 0 ) {
00222 Log(LOG_VERBOSE, ":setupResolution() RGB24:24 not supported. Trying RGB565:16 .." );
00223 this->vpic.palette = VIDEO_PALETTE_RGB565;
00224 this->vpic.depth = 16;
00225 if( ioctl(this->fd,VIDIOCSPICT, &this->vpic) == -1 ) {
00226 Log(LOG_VERBOSE, ":setupResolution() RGB565:16 not supported. Trying VIDEO_PALETTE_RGB555:15 .." );
00227 this->vpic.palette = VIDEO_PALETTE_RGB555;
00228 this->vpic.depth = 15;
00229 if( ioctl(this->fd, VIDIOCSPICT, &this->vpic) == -1 ) {
00230 Log(LOG_CRITICAL, ":setupResolution() FAILED : Unable to find a supported Capture format" );
00231 return WRET_ERR_INTERNAL;
00232 }
00233 }
00234 }
00235 Log(LOG_INFO, ":setupResolution() : Resolution: RGB / %d bpp", this->vpic.depth );
00236 }
00237 if ( this->win.width <= 0 || this->win.height <= 0 ) {
00238 Log(LOG_CRITICAL, ":setupResolution() FAILED : Invalid size [%d,%d]", this->win.width, this->win.height );
00239 return WRET_ERR_INTERNAL;
00240 }
00241 if ( this->videoBuffer != NULL )
00242 delete [] videoBuffer; this->videoBuffer = NULL;
00243
00244 Log(LOG_DEBUG, ":setupResolution() Allocating buffer [%d,%d] * 3", this->win.width, this->win.height );
00245 this->videoBufferSize = this->win.width * this->win.height * 3;
00246 this->videoBuffer = new unsigned char[this->videoBufferSize];
00247 return WRET_OK;
00248 }
00249
00250
00251
00252
00253 WRESULT Video4Linux1::extractFrame( unsigned char* buffer, long size ) {
00254 if ( buffer == NULL ) return WRET_ERR_PARAM;
00255 if ( this->fd == -1 ) return WRET_ERR_ILLEGAL_USE;
00256 read( this->fd, buffer, size );
00257 return WRET_OK;
00258 }
00259
00260
00261
00262
00263
00264
00265