00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023
00024 #include <deque>
00025 #include <unistd.h>
00026 #include <string>
00027 #include <sstream>
00028 #include <iostream>
00029 #include <iomanip>
00030
00031 using std::ostringstream;
00032 using std::setw;
00033 using std::setfill;
00034
00035 #include <pthread.h>
00036
00037 #include "v4l.h"
00038 #include "kino_av_pipe.h"
00039 #include "kino_common.h"
00040 #include "filehandler.h"
00041
00042 extern "C"
00043 {
00044 #include "support.h"
00045 #include <sys/types.h>
00046 #include <sys/soundcard.h>
00047 #include <sys/time.h>
00048 #include <unistd.h>
00049 #include <fcntl.h>
00050 #include <sys/stat.h>
00051 #include <sys/ioctl.h>
00052 #include <sys/mman.h>
00053
00054 pthread_t v4lthread;
00055 }
00056
00057 static int ENCODE_YUV = 0;
00058
00062 bool V4LDevice::request( int req, V4LStruct *v4l )
00063 {
00064 ENCODE_YUV = getenv( "KINO_V4L_FFMPEG" ) != NULL;
00065 return request( req, v4l->getStruct() );
00066 }
00067
00071 bool V4LDevice::request( int req, void *addr )
00072 {
00073 return ioctl( getHandle(), req, addr ) != -1;
00074 }
00075
00076 V4LCapability::V4LCapability( V4LDevice *device )
00077 {
00078 device->request( VIDIOCGCAP, this );
00079 }
00080
00081 V4LCapability::~V4LCapability()
00082 {
00083 cout << "Closing Capability" << endl;
00084 }
00085
00086 void *V4LCapability::getStruct()
00087 {
00088 return & capability;
00089 }
00090
00091 char *V4LCapability::getName()
00092 {
00093 return capability.name;
00094 }
00095
00096 int V4LCapability::getNumberOfChannels()
00097 {
00098 return capability.channels;
00099 }
00100
00101 int V4LCapability::getNumberOfAudioDevices()
00102 {
00103 return capability.audios;
00104 }
00105
00106 int V4LCapability::getMinWidth()
00107 {
00108 return capability.minwidth;
00109 }
00110
00111 int V4LCapability::getMinHeight()
00112 {
00113 return capability.minheight;
00114 }
00115
00116 int V4LCapability::getMaxWidth()
00117 {
00118 return capability.maxwidth;
00119 }
00120
00121 int V4LCapability::getMaxHeight()
00122 {
00123 return capability.maxheight;
00124 }
00125
00126 bool V4LCapability::canCapture()
00127 {
00128 return capability.type & VID_TYPE_CAPTURE;
00129 }
00130
00131 bool V4LCapability::hasTuner()
00132 {
00133 return capability.type & VID_TYPE_TUNER;
00134 }
00135
00136 bool V4LCapability::hasChromakey()
00137 {
00138 return capability.type & VID_TYPE_CHROMAKEY;
00139 }
00140
00141 bool V4LCapability::hasClipping()
00142 {
00143 return capability.type & VID_TYPE_CLIPPING;
00144 }
00145
00146 bool V4LCapability::hasOverwrite()
00147 {
00148 return capability.type & VID_TYPE_FRAMERAM;
00149 }
00150
00151 bool V4LCapability::hasScaling()
00152 {
00153 return capability.type & VID_TYPE_SCALES;
00154 }
00155
00156 bool V4LCapability::isMonochrome()
00157 {
00158 return capability.type & VID_TYPE_MONOCHROME;
00159 }
00160
00161 bool V4LCapability::canSubCapture()
00162 {
00163 return capability.type & VID_TYPE_SUBCAPTURE;
00164 }
00165
00166 void V4LCapability::report()
00167 {
00168 cout << ">>> Name : " << this->getName() << endl;
00169 cout << ">>> Channels : " << this->getNumberOfChannels() << endl;
00170 cout << ">>> Audio : " << this->getNumberOfAudioDevices() << endl;
00171 cout << ">>> Min Size : " << this->getMinWidth() << "," << this->getMinHeight() << endl;
00172 cout << ">>> Max Size : " << this->getMaxWidth() << "," << this->getMaxHeight() << endl;
00173 cout << ">>> Functions: " << endl;
00174 if ( this->canCapture() )
00175 cout << " + Can capture to memory" << endl;
00176 if ( this->hasTuner() )
00177 cout << " + Has a Tuner" << endl;
00178 if ( this->hasChromakey() )
00179 cout << " with Chromakey" << endl;
00180 if ( this->hasClipping() )
00181 cout << " with Clipping" << endl;
00182 if ( this->hasOverwrite() )
00183 cout << " overwrites buffer memory" << endl;
00184 if ( this->hasScaling() )
00185 cout << " + Has hardware support for image scaling" << endl;
00186 if ( this->isMonochrome() )
00187 cout << " - Monochrome only" << endl;
00188 if ( this->canSubCapture() )
00189 cout << " + Can capture part of the image" << endl;
00190 }
00191
00192 V4LTuner::V4LTuner( V4LDevice *device, int index )
00193 {
00194 this->device = device;
00195 this->tuner.tuner = index;
00196 this->device->request( VIDIOCGTUNER, this );
00197 }
00198
00199 void *V4LTuner::getStruct()
00200 {
00201 return & tuner;
00202 }
00203
00204 void V4LTuner::report()
00205 {}
00206
00207 int V4LTuner::getRangeLow()
00208 {
00209 return tuner.rangelow;
00210 }
00211
00212 void V4LTuner::setRangeLow( int low )
00213 {
00214 tuner.rangelow = low;
00215 }
00216
00217 int V4LTuner::getRangeHigh()
00218 {
00219 return tuner.rangehigh;
00220 }
00221
00222 void V4LTuner::setRangeHigh( int high )
00223 {
00224 tuner.rangehigh = high;
00225 }
00226
00227 int V4LTuner::getFlags()
00228 {
00229 return tuner.flags;
00230 }
00231
00232 void V4LTuner::setFlags( int flags )
00233 {
00234 tuner.flags = flags;
00235 }
00236
00237 int V4LTuner::getMode()
00238 {
00239 return tuner.mode;
00240 }
00241
00242 void V4LTuner::setMode( int mode )
00243 {
00244 tuner.mode = mode;
00245 }
00246
00247 int V4LTuner::getSignal()
00248 {
00249 return tuner.signal;
00250 }
00251
00252 V4LChannel::V4LChannel( V4LDevice *device, int index )
00253 {
00254 memset( &channel, 0, sizeof( struct video_channel ) );
00255 this->device = device;
00256 this->channel.channel = index;
00257 device->request( VIDIOCGCHAN, this );
00258 device->request( VIDIOCSCHAN, this );
00259 for ( unsigned int i = 0; i < getNumberOfTuners(); i ++ )
00260 {
00261 V4LTuner *tuner = new V4LTuner( this->device, i );
00262 tuners.insert( tuners.end(), tuner );
00263 }
00264 }
00265
00266 V4LChannel::~V4LChannel()
00267 {
00268 cout << "Channel destroyed" << endl;
00269 }
00270
00271 void *V4LChannel::getStruct()
00272 {
00273 return & channel;
00274 }
00275
00276 char *V4LChannel::getName()
00277 {
00278 return channel.name;
00279 }
00280
00281 bool V4LChannel::setTuner( unsigned int index )
00282 {
00283 if ( index >= 0 && index < tuners.size() )
00284 {
00285 current = tuners[ index ];
00286
00287 current->setRangeLow( 0 );
00288 current->setRangeHigh( 0xffff );
00289 return device->request( VIDIOCSTUNER, current );
00290 }
00291 else
00292 {
00293 return false;
00294 }
00295 }
00296
00297 unsigned int V4LChannel::getNumberOfTuners()
00298 {
00299 return channel.tuners;
00300 }
00301
00302 V4LTuner *V4LChannel::getTuner( unsigned int index )
00303 {
00304 if ( index >= 0 && index < tuners.size() )
00305 {
00306 return tuners[ index ];
00307 }
00308 else
00309 {
00310 return NULL;
00311 }
00312 }
00313
00314 int V4LChannel::getSignal()
00315 {
00316 device->request( VIDIOCGTUNER, current );
00317 return current->getSignal();
00318 }
00319
00320 void V4LChannel::report()
00321 {
00322 cout << ">>>> Channel # " << channel.channel << endl;
00323 cout << ">>>> Name : " << this->getName() << endl;
00324 cout << ">>>> Tuners : " << this->getNumberOfTuners() << endl;
00325 cout << ">>>> Flags : " << endl;
00326 if ( channel.flags & VIDEO_VC_TUNER )
00327 cout << " Channel has tuners" << endl;
00328 if ( channel.flags & VIDEO_VC_AUDIO )
00329 cout << " Channel has audio" << endl;
00330 cout << ">>>> Type : " << endl;
00331 if ( channel.type & VIDEO_TYPE_TV )
00332 cout << " TV" << endl;
00333 if ( channel.type & VIDEO_TYPE_CAMERA )
00334 cout << " Camera" << endl;
00335 }
00336
00340 V4L::V4L()
00341 {
00342 cout << "Opening V4L" << endl;
00343 }
00344
00345 void V4L::setInfo( char *device, char *input, char *audio, int sample )
00346 {
00347 this->device = device;
00348 this->input = input;
00349 this->audio = audio;
00350 this->sample = sample;
00351 }
00352
00353 bool V4L::openDevice()
00354 {
00355 bool ret = true;
00356
00357 if ( !strcmp( this->input, "PAL" ) )
00358 {
00359 this->width = 720;
00360 this->height = 576;
00361 this->fps = 25;
00362 this->frameSample = this->sample / this->fps;
00363 }
00364 else if ( !strcmp( this->input, "NTSC" ) )
00365 {
00366 this->width = 720;
00367 this->height = 480;
00368 this->fps = 30;
00369 this->frameSample = this->sample / this->fps;
00370 }
00371
00372 this->current = NULL;
00373 this->fd = open( device, O_RDWR );
00374 if ( fd != -1 )
00375 {
00376 this->capability = new V4LCapability( this );
00377 for ( int index = 0; index < capability->getNumberOfChannels(); index ++ )
00378 {
00379 V4LChannel *channel = new V4LChannel( this, index );
00380 channels.insert( channels.end(), channel );
00381 }
00382 setCaptureResolution( this->width, this->height );
00383 }
00384 else
00385 {
00386 perror( "Unable to open video device" );
00387 ret = false;
00388 }
00389 return ret;
00390 }
00391
00395 V4L::~V4L()
00396 {
00397 cout << "Closing V4L" << endl;
00398 if ( fd != -1 )
00399 {
00400 close( fd );
00401 for ( unsigned int index = 0; index < channels.size(); index ++ )
00402 delete channels[ index ];
00403 delete this->capability;
00404 }
00405 }
00406
00412 bool V4L::deviceAvailable()
00413 {
00414 return fd != -1;
00415 }
00416
00422 int V4L::getHandle()
00423 {
00424 return fd;
00425 }
00426
00433 bool V4L::setChannel( unsigned int channel )
00434 {
00435 if ( channel >= 0 && channel < channels.size() )
00436 {
00437 current = channels[ channel ];
00438 return this->request( VIDIOCSCHAN, current );
00439 }
00440 else
00441 {
00442 return false;
00443 }
00444 }
00445
00451 unsigned int V4L::getNumberOfChannels()
00452 {
00453 return channels.size();
00454 }
00455
00462 V4LChannel *V4L::getChannel( unsigned int channel )
00463 {
00464 if ( channel >= 0 && channel < channels.size() )
00465 return channels[ channel ];
00466 else
00467 return NULL;
00468 }
00469
00476 bool V4L::setTuner( unsigned int tuner )
00477 {
00478 if ( current != NULL )
00479 return current->setTuner( tuner );
00480 else
00481 return false;
00482 }
00483
00489 unsigned int V4L::getNumberOfTuners( )
00490 {
00491 if ( current != NULL )
00492 return current->getNumberOfTuners();
00493 else
00494 return 0;
00495 }
00496
00503 V4LTuner *V4L::getTuner( unsigned int tuner )
00504 {
00505 if ( current != NULL )
00506 return current->getTuner( tuner );
00507 else
00508 return NULL;
00509 }
00510
00517 bool V4L::setCaptureResolution( int width, int height )
00518 {
00519 if ( width > capability->getMaxWidth() ||
00520 width < capability->getMinWidth() )
00521 return false;
00522 if ( height > capability->getMaxHeight() ||
00523 height < capability->getMinHeight() )
00524 return false;
00525 if ( !capability->hasScaling() && (
00526 width != capability->getMaxWidth() ||
00527 height != capability->getMaxHeight() ) )
00528 return false;
00529 this->width = width;
00530 this->height = height;
00531 cout << "Capture resolution set to " << width << ", " << height << endl;
00532 return true;
00533 }
00534
00540 int V4L::getWidth()
00541 {
00542 return width;
00543 }
00544
00550 int V4L::getHeight()
00551 {
00552 return height;
00553 }
00554
00558 void V4L::startAudio()
00559 {
00560 struct video_audio audio;
00561 ioctl( fd, VIDIOCGAUDIO, &audio );
00562 if ( audio.flags & VIDEO_AUDIO_MUTE )
00563 audio.flags ^= VIDEO_AUDIO_MUTE;
00564 cout << "Volume : " << audio.volume << endl;
00565 audio.volume = 65535;
00566 ioctl( fd, VIDIOCSAUDIO, &audio );
00567 }
00568
00572 void V4L::stopAudio()
00573 {
00574 struct video_audio audio;
00575 ioctl( fd, VIDIOCGAUDIO, &audio );
00576 audio.flags |= VIDEO_AUDIO_MUTE;
00577 cout << "Volume : " << audio.volume << endl;
00578 audio.volume = 0;
00579 ioctl( fd, VIDIOCSAUDIO, &audio );
00580 }
00581
00582 int V4L::mappedMemorySize( bool init )
00583 {
00584 static video_mbuf buf;
00585 if ( init == true )
00586 {
00587 init = 1;
00588 ioctl( fd, VIDIOCGMBUF, &buf );
00589 cout << ">>> Mapped Memory Size = " << buf.size << " frames are " << buf.frames << endl;
00590 frame_maps = buf.frames;
00591 }
00592 return buf.size;
00593 }
00594
00601 bool V4L::initialiseCapture( int format )
00602 {
00603 size = width * height * 4;
00604
00605 map = mmap( 0, mappedMemorySize( true ), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
00606
00607 if ( map != NULL )
00608 {
00609 for ( int i = 0; i < frame_maps; i ++ )
00610 {
00611 frame[ i ].frame = i;
00612 frame[ i ].width = getWidth();
00613 frame[ i ].height = getHeight();
00614 frame[ i ].format = format;
00615 }
00616
00617 struct timeval tv;
00618 gettimeofday( &tv, NULL );
00619 starttime = tv.tv_sec * 1000000 + tv.tv_usec;
00620 frames = 0;
00621 frame_next = 0;
00622
00623 int retry = 0;
00624 while ( ioctl( fd, VIDIOCMCAPTURE, &frame[ 0 ] ) == -1 && retry ++ < frame_maps + 1 ) ;
00625
00626 return true;
00627 }
00628 else
00629 {
00630 return false;
00631 }
00632 }
00633
00639 void *V4L::getNextFrame()
00640 {
00641 unsigned char * ret = NULL;
00642
00643 int current = frame_next;
00644 frame_next = ( frame_next + 1 ) % frame_maps;
00645
00646 if ( ioctl( fd, VIDIOCMCAPTURE, &frame[ frame_next ] ) == -1 )
00647 ;
00648 if ( ioctl( fd, VIDIOCSYNC, &frame[ current ].frame ) == -1 )
00649 ;
00650 ret = ( unsigned char * ) map + current * ( mappedMemorySize( ) / frame_maps );
00651
00652 frames ++;
00653
00654 return ( void * ) ret;
00655 }
00656
00660 void V4L::stopCapture()
00661 {
00662 if ( map != NULL )
00663 {
00664 struct timeval tv;
00665 gettimeofday( &tv, NULL );
00666 long long endtime = tv.tv_sec * 1000000 + tv.tv_usec;
00667 double fps = ( frames ) / ( ( ( double ) ( endtime - starttime ) ) / 1000000 );
00668 cout << "fps: " << fps << endl;
00669 munmap( map, mappedMemorySize() );
00670 map = NULL;
00671 int enable = 0;
00672 ioctl( getHandle(), VIDIOCCAPTURE, &enable );
00673 }
00674 }
00675
00681 int V4L::getFrequency()
00682 {
00683 unsigned long current;
00684 ioctl( fd, VIDIOCGFREQ, ¤t );
00685 return ( int ) current;
00686 }
00687
00694 bool V4L::setFrequency( int frequency )
00695 {
00696 unsigned long val = ( unsigned long ) frequency & 0xffff;
00697 return ioctl( fd, VIDIOCSFREQ, &val ) != -1;
00698 }
00699
00703 int V4L::getSignal()
00704 {
00705 return current->getSignal();
00706 }
00707
00711 void V4L::report()
00712 {
00713 capability->report();
00714
00715 for ( unsigned int index = 0; index < channels.size(); index ++ )
00716 {
00717 channels[ index ] ->report();
00718 }
00719 }
00720
00721
00726 EncoderFrame::EncoderFrame()
00727 {
00728 image = new uint8_t[ 720 * 576 * 3 ];
00729 }
00730
00731 EncoderFrame::~EncoderFrame()
00732 {
00733 delete[] image;
00734 }
00735
00736 void EncoderFrame::setVideo( void *image, int width, int height )
00737 {
00738 if ( ENCODE_YUV )
00739 memcpy( this->image, ( unsigned char * ) image, width * height * 2 );
00740 else
00741 memcpy( this->image, ( unsigned char * ) image, ( width * height * 3 ) / 2 );
00742
00743 this->width = width;
00744 this->height = height;
00745 }
00746
00747 void EncoderFrame::setAudio( void *audio, int length )
00748 {
00749 memcpy( this->audio, audio, length );
00750 this->length = length;
00751 }
00752
00757 deque < EncoderFrame * > DvEncoder::used;
00758 deque < EncoderFrame * > DvEncoder::available;
00759
00760 DvEncoder::DvEncoder( char *filename, int width, int height ) : active( false ), audio( "/dev/dsp" )
00761 {
00762 this->width = width;
00763 this->height = height;
00764
00765 this->filename = filename;
00766 for ( int i = 0; i < Preferences::getInstance().dvCaptureBuffers; ++i )
00767 {
00768 available.push_back( NULL );
00769 }
00770
00771 pthread_mutex_init( &mutex, NULL );
00772 pthread_create( &thread, NULL, startThread, this );
00773 }
00774
00775 DvEncoder::~DvEncoder( )
00776 {
00777 active = false;
00778 pthread_join( thread, NULL );
00779
00780 for ( int i = available.size(); i > 0; --i )
00781 {
00782 EncoderFrame *frame = available[ 0 ];
00783 available.pop_front();
00784 delete frame;
00785 }
00786
00787 for ( int i = used.size(); i > 0; --i )
00788 {
00789 EncoderFrame *frame = used[ 0 ];
00790 used.pop_front();
00791 delete frame;
00792 }
00793 }
00794
00795 EncoderFrame *DvEncoder::getFrame()
00796 {
00797 EncoderFrame * frame = NULL;
00798
00799 pthread_mutex_lock( &mutex );
00800 if ( available.size() > 0 )
00801 {
00802 frame = available[ 0 ];
00803 if ( frame == NULL )
00804 frame = new EncoderFrame;
00805
00806 available.pop_front();
00807 }
00808 pthread_mutex_unlock( &mutex );
00809
00810 return frame;
00811 }
00812
00813 void DvEncoder::doneWithFrame( EncoderFrame *frame )
00814 {
00815 pthread_mutex_lock( &mutex );
00816 used.push_back( frame );
00817 pthread_mutex_unlock( &mutex );
00818 }
00819
00820 void *DvEncoder::startThread( void *ptr )
00821 {
00822 DvEncoder * encoder = ( DvEncoder * ) ptr;
00823 cout << "starting encoder thread..." << endl;
00824 encoder->writeThread( );
00825 return NULL;
00826 }
00827
00828 void DvEncoder::writeThread()
00829 {
00830 struct timespec tm =
00831 {
00832 0, 0
00833 };
00834 char command[ 10240 ];
00835 int counter = 0;
00836 struct stat stats;
00837 string thisfile;
00838
00839 active = true;
00840
00841 do
00842 {
00843 ostringstream sb;
00844 sb << filename << setfill( '0' ) << setw( 3 ) << ++ counter << ".dv";
00845 thisfile = sb.str();
00846 cout << ">>> Trying " << thisfile << endl;
00847 }
00848 while ( stat( thisfile.c_str(), &stats ) == 0 );
00849
00850 KinoVideoPipe *encode = NULL;
00851
00852 if ( ENCODE_YUV )
00853 {
00854 encode = KinoVideoFactory::CreateVideoPipe( PIPE_VIDEO_DV_YUV );
00855 sprintf( command, "ffmpeg -threads 2 -f yuv4mpegpipe -i pipe: -f audio_device -ac 2 -ar 48000 -i %s -y %s", audio, thisfile.c_str() );
00856
00857 }
00858 else
00859 {
00860 encode = KinoVideoFactory::CreateVideoPipe( PIPE_VIDEO_DV_PGM );
00861 sprintf( command, "encodedv -a dsp -i pgm -p 2 -q 2 - %s > %s", audio, thisfile.c_str() );
00862 }
00863
00864 encode->OpenVideoPipe( command, width, height );
00865
00866 while ( active || used.size() > 0 )
00867 {
00868 if ( used.size() > 0 )
00869 {
00870 pthread_mutex_lock( &mutex );
00871 EncoderFrame *frame = used.front();
00872 used.pop_front();
00873 pthread_mutex_unlock( &mutex );
00874
00875 if ( frame != NULL )
00876 {
00877 if ( ENCODE_YUV )
00878 encode->OutputVideoFrame( frame->image, width * height * 2 );
00879 else
00880 encode->OutputVideoFrame( frame->image, width * height * 3 / 2 );
00881
00882 pthread_mutex_lock( &mutex );
00883 available.push_back( frame );
00884 pthread_mutex_unlock( &mutex );
00885 }
00886 }
00887
00888 nanosleep( &tm, NULL );
00889 }
00890
00891 encode->CloseVideo();
00892
00893 delete encode;
00894
00895 FileTracker::GetInstance().Add( thisfile.c_str() );
00896 }
00897
00902 extern "C"
00903 {
00904 static void *gdkv4l_thread( void * ptr )
00905 {
00906 GDKV4L * v4l = ( GDKV4L * ) ptr;
00907 v4l->active = true;
00908 if ( !v4l->capturing )
00909 {
00910 while ( v4l->active )
00911 {
00912 v4l->draw();
00913 struct timespec t =
00914 {
00915 0, 0
00916 };
00917 nanosleep( &t, NULL );
00918 }
00919 }
00920 else
00921 {
00922 char filename[ 1024 ];
00923 GtkEntry *fileEntry = GTK_ENTRY( lookup_widget( v4l->widget, "entry_v4l_file" ) );
00924 strcpy( filename, gtk_entry_get_text( fileEntry ) );
00925
00926 DvEncoder *encoder = new DvEncoder( filename, v4l->getWidth(), v4l->getHeight() );
00927 encoder->audio = v4l->audio;
00928 while ( v4l->active )
00929 {
00930 v4l->capture( encoder );
00931 struct timespec t =
00932 {
00933 0, 0
00934 };
00935 nanosleep( &t, NULL );
00936 }
00937 delete encoder;
00938 }
00939 return NULL;
00940 }
00941 }
00942
00943 GDKV4L::GDKV4L( GtkWidget *widget ) : V4L(), active( false ), capturing( false )
00944 {
00945 cout << "Starting GDKV4L" << endl;
00946 this->widget = widget;
00947 this->displayer = NULL;
00948 }
00949
00950 GDKV4L::~GDKV4L()
00951 {
00952 cout << "Closing GDKV4L" << endl;
00953 stopCapturing();
00954 stopVideo();
00955 }
00956
00957 void GDKV4L::startVideo()
00958 {
00959 cout << ">>> Starting video" << endl;
00960 if ( !active )
00961 {
00962 pthread_create( &v4lthread, NULL, gdkv4l_thread, this );
00963 }
00964 }
00965
00966 void GDKV4L::startCapturing()
00967 {
00968 if ( !capturing )
00969 {
00970 stopVideo();
00971 capturing = true;
00972 startVideo();
00973 }
00974 }
00975
00976 void GDKV4L::stopVideo()
00977 {
00978 cout << ">>> Stopping video" << endl;
00979 if ( active )
00980 {
00981 active = false;
00982 gdk_threads_leave();
00983 pthread_join( v4lthread, NULL );
00984 gdk_threads_enter();
00985 this->stopCapture();
00986 }
00987 if ( displayer != NULL )
00988 {
00989 delete displayer;
00990 displayer = NULL;
00991 }
00992 }
00993
00994 void GDKV4L::stopCapturing()
00995 {
00996 if ( capturing )
00997 {
00998 stopVideo();
00999 capturing = false;
01000 startVideo();
01001 }
01002 }
01003
01004 void GDKV4L::draw()
01005 {
01006
01007 if ( displayer == NULL )
01008 {
01009 gdk_threads_enter();
01010 displayer = FindDisplayer::getDisplayer( widget, getWidth(), getHeight() );
01011
01012 switch ( displayer->format() )
01013 {
01014 case DISPLAY_YUV:
01015 input = DISPLAY_YUV;
01016 initialiseCapture( VIDEO_PALETTE_YUV422 );
01017 break;
01018 case DISPLAY_RGB:
01019 input = DISPLAY_BGR;
01020 initialiseCapture( VIDEO_PALETTE_RGB24 );
01021 break;
01022 case DISPLAY_RGB16:
01023 input = DISPLAY_RGB16;
01024 initialiseCapture( VIDEO_PALETTE_RGB565 );
01025 break;
01026 default:
01027 break;
01028 }
01029 gdk_threads_leave();
01030 }
01031
01032 void *f = getNextFrame();
01033
01034 if ( f != NULL )
01035 {
01036 gdk_threads_enter();
01037 displayer->put( input, f, getWidth(), getHeight() );
01038 gdk_flush();
01039 gdk_threads_leave();
01040 }
01041 }
01042
01043 void GDKV4L::capture( DvEncoder *encoder )
01044 {
01045
01046 static int count = 0;
01047 void *f = NULL;
01048
01049 if ( displayer == NULL )
01050 {
01051 gdk_threads_enter();
01052 displayer = FindDisplayer::getDisplayer( widget, getWidth(), getHeight() );
01053
01054 if ( ENCODE_YUV )
01055 {
01056 input = DISPLAY_YUV;
01057 initialiseCapture( VIDEO_PALETTE_YUV422P );
01058 }
01059 else
01060 {
01061 input = DISPLAY_RGB;
01062 initialiseCapture( VIDEO_PALETTE_YUV420P );
01063 }
01064
01065
01066 f = getNextFrame();
01067
01068 gdk_threads_leave();
01069 }
01070
01071
01072 f = getNextFrame();
01073
01074 if ( f != NULL )
01075 {
01076 EncoderFrame * frame = encoder->getFrame();
01077 if ( frame != NULL )
01078 {
01079 frame->setVideo( f, getWidth(), getHeight() );
01080 encoder->doneWithFrame( frame );
01081 }
01082 else
01083 {
01084 cout << "No frames available..." << endl;
01085 }
01086 }
01087
01088
01089
01090 if ( f != NULL && displayer->format() == input && ( ++ count ) % 25 == 0 )
01091 {
01092 gdk_threads_enter();
01093 displayer->put( input, f, getWidth(), getHeight() );
01094 gdk_flush();
01095 gdk_threads_leave();
01096 }
01097 }
01098