Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

ieee1394io.cc

Go to the documentation of this file.
00001 /*
00002 * ieee1394io.cc -- asynchronously grabbing DV data
00003 * Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
00004 * Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
00005 *
00006 * This program is free software; you can redistribute it and/or modify
00007 * it under the terms of the GNU General Public License as published by
00008 * the Free Software Foundation; either version 2 of the License, or
00009 * (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU General Public License
00017 * along with this program; if not, write to the Free Software Foundation,
00018 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 */
00020 
00047 #ifdef HAVE_CONFIG_H
00048 #include <config.h>
00049 #endif
00050 
00051 #include <deque>
00052 #include <iostream>
00053 
00054 using std::cerr;
00055 using std::endl;
00056 
00057 #include <assert.h>
00058 #include <unistd.h>
00059 #include <fcntl.h>
00060 #include <pthread.h>
00061 #include <sys/ioctl.h>
00062 #include <sys/mman.h>
00063 #include <sys/poll.h>
00064 #include <errno.h>
00065 #include <time.h>
00066 #include <sys/time.h>
00067 
00068 #include <libavc1394/avc1394.h>
00069 #include <libavc1394/avc1394_vcr.h>
00070 #include <libavc1394/rom1394.h>
00071 
00072 #include "ieee1394io.h"
00073 #include "preferences.h"
00074 #include "kino_common.h"
00075 #include "page_capture.h"
00076 #include "frame.h"
00077 #include "error.h"
00078 #include "message.h"
00079 #include "commands.h"
00080 
00081 
00096 IEEE1394Reader::IEEE1394Reader( int c, int bufSize ) :
00097     droppedFrames( 0 ),
00098     currentFrame( NULL ),
00099     channel( c ),
00100     isRunning( false )
00101 {
00102     Frame * frame;
00103 
00104     /* Create empty frames and put them in our inFrames queue */
00105     for ( int i = 0; i < bufSize; ++i )
00106     {
00107         frame = GetFramePool( ) ->GetFrame( );
00108         inFrames.push_back( frame );
00109     }
00110 
00111     /* Initialize mutexes */
00112     pthread_mutex_init( &mutex, NULL );
00113 
00114     /* Initialise mutex and condition for action triggerring */
00115     pthread_mutex_init( &condition_mutex, NULL );
00116     pthread_cond_init( &condition, NULL );
00117 }
00118 
00119 
00129 IEEE1394Reader::~IEEE1394Reader()
00130 {
00131     Frame * frame;
00132 
00133     for ( int i = inFrames.size(); i > 0; --i )
00134     {
00135         frame = inFrames[ 0 ];
00136         inFrames.pop_front();
00137         GetFramePool( ) ->DoneWithFrame( frame );
00138     }
00139     for ( int i = outFrames.size(); i > 0; --i )
00140     {
00141         frame = outFrames[ 0 ];
00142         outFrames.pop_front();
00143         GetFramePool( ) ->DoneWithFrame( frame );
00144     }
00145     if ( currentFrame != NULL )
00146     {
00147         GetFramePool( ) ->DoneWithFrame( currentFrame );
00148         currentFrame = NULL;
00149     }
00150     pthread_mutex_destroy( &condition_mutex );
00151     pthread_cond_destroy( &condition );
00152 }
00153 
00154 
00169 Frame* IEEE1394Reader::GetFrame()
00170 {
00171     Frame * frame = NULL;
00172 
00173     pthread_mutex_lock( &mutex );
00174 
00175     if ( outFrames.size() > 0 )
00176     {
00177         frame = outFrames[ 0 ];
00178         outFrames.pop_front();
00179     }
00180     pthread_mutex_unlock( &mutex );
00181     if ( frame != NULL )
00182         frame->ExtractHeader();
00183 
00184     return frame;
00185 }
00186 
00187 
00191 void IEEE1394Reader::DoneWithFrame( Frame* frame )
00192 {
00193     pthread_mutex_lock( &mutex );
00194     inFrames.push_back( frame );
00195     pthread_mutex_unlock( &mutex );
00196 }
00197 
00198 
00202 int IEEE1394Reader::GetDroppedFrames( void )
00203 {
00204     pthread_mutex_lock( &mutex );
00205     int n = droppedFrames;
00206     droppedFrames = 0;
00207     pthread_mutex_unlock( &mutex );
00208     return n;
00209 }
00210 
00211 
00218 void IEEE1394Reader::Flush()
00219 {
00220     Frame * frame = NULL;
00221 
00222     pthread_mutex_lock( &mutex );
00223     for ( int i = outFrames.size(); i > 0; --i )
00224     {
00225         frame = outFrames[ 0 ];
00226         outFrames.pop_front();
00227         inFrames.push_back( frame );
00228     }
00229     if ( currentFrame != NULL )
00230     {
00231         inFrames.push_back( currentFrame );
00232         currentFrame = NULL;
00233     }
00234     pthread_mutex_unlock( &mutex );
00235 }
00236 
00237 bool IEEE1394Reader::WaitForAction( int seconds )
00238 {
00239     pthread_mutex_lock( &mutex );
00240     int size = outFrames.size( );
00241     pthread_mutex_unlock( &mutex );
00242 
00243     if ( size == 0 )
00244     {
00245         pthread_mutex_lock( &condition_mutex );
00246         if ( seconds == 0 )
00247         {
00248             pthread_cond_wait( &condition, &condition_mutex );
00249             pthread_mutex_unlock( &condition_mutex );
00250             pthread_mutex_lock( &mutex );
00251             size = outFrames.size( );
00252         }
00253         else
00254         {
00255             struct timeval tp;
00256             struct timespec ts;
00257             int result;
00258 
00259             gettimeofday( &tp, NULL );
00260             ts.tv_sec = tp.tv_sec + seconds;
00261             ts.tv_nsec = tp.tv_usec * 1000;
00262 
00263             result = pthread_cond_timedwait( &condition, &condition_mutex, &ts );
00264             pthread_mutex_unlock( &condition_mutex );
00265             pthread_mutex_lock( &mutex );
00266 
00267             if ( result == ETIMEDOUT )
00268                 size = 0;
00269             else
00270                 size = outFrames.size();
00271         }
00272         pthread_mutex_unlock( &mutex );
00273     }
00274 
00275     return size != 0;
00276 }
00277 
00278 
00279 void IEEE1394Reader::TriggerAction( )
00280 {
00281     pthread_mutex_lock( &condition_mutex );
00282     pthread_cond_signal( &condition );
00283     pthread_mutex_unlock( &condition_mutex );
00284 }
00285 
00286 
00287 #ifdef HAVE_IEC61883
00288 
00299 iec61883Reader::iec61883Reader( int c, int bufSize ) :
00300     IEEE1394Reader( c, bufSize )
00301 {
00302     m_handle = NULL;
00303     cerr << ">>> Using iec61883 capture" << endl;
00304 }
00305 
00306 
00307 iec61883Reader::~iec61883Reader()
00308 {
00309     StopThread();
00310 }
00311 
00312 
00321 bool iec61883Reader::StartThread( int port )
00322 {
00323     if ( isRunning )
00324         return true;
00325     if ( port < 0 )
00326         return false;
00327     cerr << ">>> iec61883Reader::StartThread on port " << port << endl;
00328 
00329     pthread_mutex_lock( &mutex );
00330     currentFrame = NULL;
00331     if ( Open( port ) && StartReceive() )
00332     {
00333         isRunning = true;
00334         pthread_create( &thread, NULL, ThreadProxy, this );
00335         pthread_mutex_unlock( &mutex );
00336         return true;
00337     }
00338     else
00339     {
00340         Close();
00341         pthread_mutex_unlock( &mutex );
00342         return false;
00343     }
00344 }
00345 
00346 
00357 void iec61883Reader::StopThread()
00358 {
00359     if ( isRunning )
00360     {
00361         isRunning = false;
00362         pthread_join( thread, NULL );
00363     }
00364     Close();
00365     Flush();
00366 }
00367 
00368 
00369 void iec61883Reader::ResetHandler( void )
00370 {
00371 }
00372 
00373 int iec61883Reader::ResetHandlerProxy( raw1394handle_t handle, unsigned int generation )
00374 {
00375     iec61883_dv_t dv = static_cast< iec61883_dv_t >( raw1394_get_userdata( handle ) );
00376     iec61883_dv_fb_t dvfb = static_cast< iec61883_dv_fb_t >( iec61883_dv_get_callback_data( dv ) );
00377     iec61883Reader *self = static_cast< iec61883Reader* >( iec61883_dv_fb_get_callback_data( dvfb ) );
00378     raw1394_update_generation( handle, generation );
00379     if ( self )
00380         self->ResetHandler();
00381     return 0;
00382 }
00383 
00384 
00390 bool iec61883Reader::Open( int port )
00391 {
00392     bool success;
00393 
00394     assert( !m_handle );
00395 
00396     try
00397     {
00398         m_handle = raw1394_new_handle_on_port( port );
00399         if ( !m_handle )
00400             return false;
00401         raw1394_set_bus_reset_handler( m_handle, this->ResetHandlerProxy );
00402 
00403         m_iec61883dv = iec61883_dv_fb_init( m_handle, HandlerProxy, this );
00404         success = ( m_iec61883dv != NULL );
00405     }
00406     catch ( string exc )
00407     {
00408         Close();
00409         cerr << exc << endl;
00410         success = false;
00411     }
00412     return success;
00413 }
00414 
00415 
00420 void iec61883Reader::Close()
00421 {
00422     if ( m_handle )
00423     {
00424         StopReceive();
00425         raw1394_destroy_handle( m_handle );
00426         m_handle = NULL;
00427     }
00428 }
00429 
00430 bool iec61883Reader::StartReceive()
00431 {
00432     bool success;
00433 
00434     /* Starting iso receive */
00435     try
00436     {
00437         fail_neg( iec61883_dv_fb_start( m_iec61883dv, channel ) );
00438         success = true;
00439     }
00440     catch ( string exc )
00441     {
00442         cerr << exc << endl;
00443         success = false;
00444     }
00445     return success;
00446 }
00447 
00448 
00449 void iec61883Reader::StopReceive()
00450 {
00451     if ( m_iec61883dv )
00452     {
00453         iec61883_dv_fb_close( m_iec61883dv );
00454         m_iec61883dv = NULL;
00455     }
00456 }
00457 
00458 int iec61883Reader::HandlerProxy( unsigned char *data, int length, int complete, 
00459     void *callback_data )
00460 {
00461     iec61883Reader *self = static_cast< iec61883Reader* >( callback_data );
00462     return self->Handler( length, complete, data );
00463 }
00464 
00465 int iec61883Reader::Handler( int length, int complete, unsigned char *data )
00466 {
00467     pthread_mutex_lock( &mutex );
00468     if ( currentFrame )
00469     {
00470         outFrames.push_back( currentFrame );
00471         currentFrame = NULL;
00472         //cerr << "reader > # inFrames: " << inFrames.size() << ", # outFrames: " << outFrames.size() << endl;
00473         TriggerAction( );
00474     }
00475     if ( inFrames.size() > 0 )
00476     {
00477         currentFrame = inFrames.front();
00478         currentFrame->bytesInFrame = 0;
00479         inFrames.pop_front();
00480         if ( outFrames.size( ) >= 25 )
00481             cerr << "reader < # inFrames: " << inFrames.size() << ", # outFrames: " << outFrames.size() << endl;
00482     }
00483     else
00484     {
00485         droppedFrames++;
00486         cerr << "reader < # dropped frames: " << droppedFrames << endl;
00487     }
00488     pthread_mutex_unlock( &mutex );
00489 
00490     if ( currentFrame )
00491     {
00492         memcpy( currentFrame->data, data, length );
00493         currentFrame->bytesInFrame = length;
00494     }
00495 
00496     return 0;
00497 }
00498 
00499 
00506 void* iec61883Reader::ThreadProxy( void* arg )
00507 {
00508     iec61883Reader* self = static_cast< iec61883Reader* >( arg );
00509     return self->Thread();
00510 }
00511 
00512 void* iec61883Reader::Thread()
00513 {
00514     struct pollfd raw1394_poll;
00515     int result;
00516 
00517     assert( m_handle );
00518     raw1394_poll.fd = raw1394_get_fd( m_handle );
00519     raw1394_poll.events = POLLIN | POLLERR | POLLHUP | POLLPRI;
00520 
00521     while ( isRunning )
00522     {
00523         while ( ( result = poll( &raw1394_poll, 1, 200 ) ) < 0 )
00524         {
00525             if ( !( errno == EAGAIN || errno == EINTR ) )
00526             {
00527                 perror( "error: raw1394 poll" );
00528                 break;
00529             }
00530         }
00531         if ( result > 0 && ( ( raw1394_poll.revents & POLLIN )
00532                 || ( raw1394_poll.revents & POLLPRI ) ) )
00533             result = raw1394_loop_iterate( m_handle );
00534     }
00535     return NULL;
00536 }
00537 #endif
00538 
00539 
00540 #ifdef HAVE_DV1394
00541 
00548 dv1394Reader::dv1394Reader( int c, int bufSize ) :
00549         IEEE1394Reader( c, bufSize )
00550 {
00551     m_dv1394_map = NULL;
00552     m_dv1394_fd = -1;
00553     cerr << ">>> Using dv1394 capture" << endl;
00554 }
00555 
00556 
00557 dv1394Reader::~dv1394Reader()
00558 {}
00559 
00560 
00569 bool dv1394Reader::StartThread( int port )
00570 {
00571     if ( isRunning )
00572         return true;
00573     pthread_mutex_lock( &mutex );
00574     currentFrame = NULL;
00575     if ( Open( port ) && StartReceive() )
00576     {
00577         isRunning = true;
00578         pthread_create( &thread, NULL, ThreadProxy, this );
00579         pthread_mutex_unlock( &mutex );
00580         return true;
00581     }
00582     else
00583     {
00584         Close();
00585         pthread_mutex_unlock( &mutex );
00586         return false;
00587     }
00588 }
00589 
00590 
00600 void dv1394Reader::StopThread()
00601 {
00602     if ( isRunning )
00603     {
00604         isRunning = false;
00605         pthread_join( thread, NULL );
00606         StopReceive();
00607         Close();
00608         Flush();
00609     }
00610     TriggerAction( );
00611 }
00612 
00613 
00619 bool dv1394Reader::Open( int port )
00620 {
00621     int n_frames = DV1394_MAX_FRAMES / 4;
00622     struct dv1394_init init =
00623         {
00624             DV1394_API_VERSION, channel, n_frames, DV1394_PAL, 0, 0, 0
00625         };
00626 
00627     m_dv1394_fd = open( Preferences::getInstance().dvCaptureDevice, O_RDWR );
00628     if ( m_dv1394_fd == -1 )
00629         return false;
00630 
00631     if ( ioctl( m_dv1394_fd, DV1394_INIT, &init ) )
00632     {
00633         perror( "dv1394 INIT ioctl" );
00634         close( m_dv1394_fd );
00635         m_dv1394_fd = -1;
00636         return false;
00637     }
00638 
00639     m_dv1394_map = ( unsigned char * ) mmap( NULL, DV1394_PAL_FRAME_SIZE * n_frames,
00640                    PROT_READ | PROT_WRITE, MAP_SHARED, m_dv1394_fd, 0 );
00641     if ( m_dv1394_map == MAP_FAILED )
00642     {
00643         perror( "mmap frame buffers" );
00644         close( m_dv1394_fd );
00645         m_dv1394_fd = -1;
00646         m_dv1394_map = NULL;
00647         return false;
00648     }
00649 
00650     return true;
00651 }
00652 
00653 
00657 void dv1394Reader::Close()
00658 {
00659     if ( m_dv1394_fd != -1 )
00660     {
00661         if ( m_dv1394_map != NULL )
00662             munmap( m_dv1394_map, DV1394_PAL_FRAME_SIZE * DV1394_MAX_FRAMES / 4 );
00663         close( m_dv1394_fd );
00664         m_dv1394_map = NULL;
00665         m_dv1394_fd = -1;
00666     }
00667 }
00668 
00669 
00670 bool dv1394Reader::StartReceive()
00671 {
00672     /* Starting iso receive */
00673     if ( ioctl( m_dv1394_fd, DV1394_START_RECEIVE, NULL ) )
00674     {
00675         perror( "dv1394 START_RECEIVE ioctl" );
00676         return false;
00677     }
00678     return true;
00679 }
00680 
00681 
00682 void dv1394Reader::StopReceive()
00683 {}
00684 
00685 bool dv1394Reader::Handler( int handle )
00686 {
00687     struct dv1394_status dvst;
00688     struct pollfd pol;
00689     int result;
00690         
00691     pol.fd = m_dv1394_fd;
00692     pol.events = POLLIN | POLLERR | POLLHUP;
00693     while ( ( result = poll( &pol, 1, 200 ) ) < 0 )
00694     {
00695         if ( !( errno == EAGAIN || errno == EINTR ) )
00696         {
00697             perror( "error: dv1394 poll" );
00698             return false;
00699         }
00700     }
00701     if ( result == 0 )
00702         return true;
00703 
00704     if ( ioctl( handle, DV1394_GET_STATUS, &dvst ) )
00705     {
00706         perror( "ioctl GET_STATUS" );
00707         return false;
00708     }
00709 
00710     if ( dvst.dropped_frames > 0 )
00711     {
00712         std:cerr << "dv1394 reported " << dvst.dropped_frames << " dropped frames." << std::endl;
00713         droppedFrames += dvst.dropped_frames;
00714     }
00715 
00716     for ( unsigned int i = 0; i < dvst.n_clear_frames; i++ )
00717     {
00718         pthread_mutex_lock( &mutex );
00719         if ( currentFrame != NULL )
00720         {
00721             outFrames.push_back( currentFrame );
00722             currentFrame = NULL;
00723             TriggerAction( );
00724             //printf("reader > out: buffer %d, output %d\n", inFrames.size(), outFrames.size());
00725             //fflush(stdout);
00726         }
00727 
00728 
00729         if ( inFrames.size() > 0 )
00730         {
00731             currentFrame = inFrames.front();
00732             currentFrame->bytesInFrame = 0;
00733             inFrames.pop_front();
00734             //printf("reader < buf: buffer %d, output %d\n", inFrames.size(), outFrames.size());
00735             //fflush(stdout);
00736         }
00737         else
00738         {
00739             droppedFrames++;
00740             cerr << "reader < # dropped frames: " << droppedFrames << endl;
00741         }
00742 
00743         pthread_mutex_unlock( &mutex );
00744 
00745         if ( currentFrame != NULL )
00746         {
00747             memcpy( currentFrame->data,
00748                     ( m_dv1394_map + ( dvst.first_clear_frame * DV1394_PAL_FRAME_SIZE ) ),
00749                     DV1394_PAL_FRAME_SIZE );
00750             currentFrame->bytesInFrame = currentFrame->GetFrameSize( );
00751         }
00752 
00753         if ( ioctl( handle, DV1394_RECEIVE_FRAMES, 1 ) )
00754         {
00755             perror( "error: ioctl RECEIVE_FRAMES" );
00756             return false;
00757         }
00758 
00759         if ( ioctl( handle, DV1394_GET_STATUS, &dvst ) )
00760         {
00761             perror( "ioctl GET_STATUS" );
00762             return false;
00763         }
00764 
00765         if ( dvst.dropped_frames > 0 )
00766         {
00767             std::cerr << "dv1394 reported " << dvst.dropped_frames << " dropped frames." << std::endl;
00768             droppedFrames += dvst.dropped_frames;
00769         }
00770 
00771     }
00772     return true;
00773 }
00774 
00775 
00782 void* dv1394Reader::ThreadProxy( void* arg )
00783 {
00784     dv1394Reader* self = static_cast< dv1394Reader* >( arg );
00785     return self->Thread();
00786 }
00787 
00788 void* dv1394Reader::Thread( )
00789 {
00790 
00791     while ( isRunning )
00792     {
00793         if ( ! Handler( m_dv1394_fd ) )
00794             break;
00795     }
00796     return NULL;
00797 }
00798 #endif
00799 
00800 
00807 AVC::AVC( void ) : port( -1 ), totalPorts( 0 )
00808 {
00809     pthread_mutex_init( &avc_mutex, NULL );
00810     avc_handle = NULL;
00811     struct raw1394_portinfo pinf[ 16 ];
00812 
00813     try
00814     {
00815         avc_handle = raw1394_new_handle();
00816         if ( avc_handle == 0 )
00817             return;
00818         fail_neg( totalPorts = raw1394_get_port_info( avc_handle, pinf, 16 ) );
00819         raw1394_destroy_handle( avc_handle );
00820         avc_handle = NULL;
00821     }
00822     catch ( string exc )
00823     {
00824         if ( avc_handle != NULL )
00825             raw1394_destroy_handle( avc_handle );
00826         avc_handle = NULL;
00827         cerr << exc << endl;
00828     }
00829     return;
00830 }
00831 
00832 
00837 AVC::~AVC()
00838 {
00839     if ( avc_handle != NULL )
00840     {
00841         pthread_mutex_lock( &avc_mutex );
00842         raw1394_destroy_handle( avc_handle );
00843         avc_handle = NULL;
00844         pthread_mutex_unlock( &avc_mutex );
00845     }
00846 }
00847 
00848 extern "C" {
00849     extern KinoCommon *common;
00850 }
00851 
00852 int AVC::ResetHandler( raw1394handle_t handle, unsigned int generation )
00853 {
00854     cerr << "Reset Handler received" << endl;
00855     raw1394_update_generation( handle, generation );
00856     common->getPageCapture()->driver_locked = true;
00857     return 0;
00858 }
00859 
00860 
00872 int AVC::isPhyIDValid( int phyID )
00873 {
00874     int value = -1;
00875     int currentNode, nodeCount;
00876     rom1394_directory rom1394_dir;
00877 
00878     pthread_mutex_lock( &avc_mutex );
00879     if ( avc_handle != NULL )
00880     {
00881         nodeCount = raw1394_get_nodecount( avc_handle );
00882         if ( phyID >= 0 && phyID < nodeCount )
00883         {
00884             if ( rom1394_get_directory( avc_handle, phyID, &rom1394_dir ) >= 0 )
00885             {
00886                 if ( rom1394_get_node_type( &rom1394_dir ) == ROM1394_NODE_TYPE_AVC )
00887                 {
00888                     if ( avc1394_check_subunit_type( avc_handle, phyID, AVC1394_SUBUNIT_TYPE_VCR ) )
00889                         value = phyID;
00890                 }
00891                 rom1394_free_directory( &rom1394_dir );
00892             }
00893         }
00894 
00895         if ( value == -1 )
00896         {
00897             raw1394_destroy_handle( avc_handle );
00898             avc_handle = NULL;
00899             port = -1;
00900         }
00901     }
00902     for ( int p = 0; value == -1 && p < totalPorts; p++ )
00903     {
00904         if ( ( avc_handle = raw1394_new_handle_on_port( p ) ) )
00905         {
00906             port = p;
00907             raw1394_set_bus_reset_handler( avc_handle, this->ResetHandler );
00908 
00909             // look for a new AVC recorder
00910             nodeCount = raw1394_get_nodecount( avc_handle );
00911             for ( currentNode = 0; value == -1 && currentNode < nodeCount; currentNode++ )
00912             {
00913                 if ( rom1394_get_directory( avc_handle, currentNode, &rom1394_dir ) >= 0 )
00914                 {
00915                     if ( rom1394_get_node_type( &rom1394_dir ) == ROM1394_NODE_TYPE_AVC )
00916                     {
00917                         if ( avc1394_check_subunit_type( avc_handle, currentNode, AVC1394_SUBUNIT_TYPE_VCR ) )
00918                         {
00919                             // set Preferences to the newly found AVC node and return
00920                             octlet_t guid = rom1394_get_guid( avc_handle, currentNode );
00921                             snprintf( Preferences::getInstance().avcGUID, 64, "%08x%08x",
00922                                 ( quadlet_t ) ( guid >> 32 ), ( quadlet_t ) ( guid & 0xffffffff ) );
00923                             value = currentNode;
00924                         }
00925                     }
00926                     rom1394_free_directory( &rom1394_dir );
00927                 }
00928             }
00929             if ( value == -1 )
00930             {
00931                 raw1394_destroy_handle( avc_handle );
00932                 avc_handle = NULL;
00933             }
00934         }
00935     }
00936     if ( value == -1 )
00937         port = -1;
00938     pthread_mutex_unlock( &avc_mutex );
00939     return value;
00940 }
00941 
00945 void AVC::Noop( void )
00946 {
00947     struct pollfd raw1394_poll;
00948     raw1394_poll.fd = raw1394_get_fd( avc_handle );
00949     raw1394_poll.events = POLLIN | POLLPRI;
00950     raw1394_poll.revents = 0;
00951     if ( poll( &raw1394_poll, 1, 100 ) > 0 )
00952     {
00953         if ( ( raw1394_poll.revents & POLLIN )
00954                 || ( raw1394_poll.revents & POLLPRI ) )
00955             raw1394_loop_iterate( avc_handle );
00956     }
00957 }
00958 
00959 
00960 int AVC::Play( int phyID )
00961 {
00962     pthread_mutex_lock( &avc_mutex );
00963     if ( avc_handle != NULL )
00964     {
00965         if ( phyID >= 0 )
00966         {
00967             if ( !avc1394_vcr_is_recording( avc_handle, phyID ) &&
00968                 avc1394_vcr_is_playing( avc_handle, phyID ) != AVC1394_VCR_OPERAND_PLAY_FORWARD )
00969                     avc1394_vcr_play( avc_handle, phyID );
00970         }
00971     }
00972     pthread_mutex_unlock( &avc_mutex );
00973     return 0;
00974 }
00975 
00976 
00977 int AVC::Pause( int phyID )
00978 {
00979     pthread_mutex_lock( &avc_mutex );
00980     if ( avc_handle != NULL )
00981     {
00982         if ( phyID >= 0 )
00983         {
00984             if ( !avc1394_vcr_is_recording( avc_handle, phyID ) &&
00985                 avc1394_vcr_is_playing( avc_handle, phyID ) != AVC1394_VCR_OPERAND_PLAY_FORWARD_PAUSE )
00986                     avc1394_vcr_pause( avc_handle, phyID );
00987         }
00988     }
00989     struct timespec t =
00990         {
00991             0, 250000000
00992         };
00993     nanosleep( &t, NULL );
00994     pthread_mutex_unlock( &avc_mutex );
00995     return 0;
00996 }
00997 
00998 
00999 int AVC::Stop( int phyID )
01000 {
01001     pthread_mutex_lock( &avc_mutex );
01002     if ( avc_handle != NULL )
01003     {
01004         if ( phyID >= 0 )
01005             avc1394_vcr_stop( avc_handle, phyID );
01006     }
01007     struct timespec t =
01008         {
01009             0, 250000000
01010         };
01011     nanosleep( &t, NULL );
01012     pthread_mutex_unlock( &avc_mutex );
01013     return 0;
01014 }
01015 
01016 
01017 int AVC::Rewind( int phyID )
01018 {
01019     pthread_mutex_lock( &avc_mutex );
01020     if ( avc_handle != NULL )
01021     {
01022         if ( phyID >= 0 )
01023             avc1394_vcr_rewind( avc_handle, phyID );
01024     }
01025     pthread_mutex_unlock( &avc_mutex );
01026     return 0;
01027 }
01028 
01029 
01030 int AVC::FastForward( int phyID )
01031 {
01032     pthread_mutex_lock( &avc_mutex );
01033     if ( avc_handle != NULL )
01034     {
01035         if ( phyID >= 0 )
01036             avc1394_vcr_forward( avc_handle, phyID );
01037     }
01038     pthread_mutex_unlock( &avc_mutex );
01039     return 0;
01040 }
01041 
01042 int AVC::Forward( int phyID )
01043 {
01044     pthread_mutex_lock( &avc_mutex );
01045     if ( avc_handle != NULL )
01046     {
01047         if ( phyID >= 0 )
01048             avc1394_vcr_next( avc_handle, phyID );
01049     }
01050     pthread_mutex_unlock( &avc_mutex );
01051     return 0;
01052 }
01053 
01054 int AVC::Back( int phyID )
01055 {
01056     pthread_mutex_lock( &avc_mutex );
01057     if ( avc_handle != NULL )
01058     {
01059         if ( phyID >= 0 )
01060             avc1394_vcr_previous( avc_handle, phyID );
01061     }
01062     pthread_mutex_unlock( &avc_mutex );
01063     return 0;
01064 }
01065 
01066 int AVC::NextScene( int phyID )
01067 {
01068     pthread_mutex_lock( &avc_mutex );
01069     if ( avc_handle != NULL )
01070     {
01071         if ( phyID >= 0 )
01072             avc1394_vcr_next_index( avc_handle, phyID );
01073     }
01074     pthread_mutex_unlock( &avc_mutex );
01075     return 0;
01076 }
01077 
01078 int AVC::PreviousScene( int phyID )
01079 {
01080     pthread_mutex_lock( &avc_mutex );
01081     if ( avc_handle != NULL )
01082     {
01083         if ( phyID >= 0 )
01084             avc1394_vcr_previous_index( avc_handle, phyID );
01085     }
01086     pthread_mutex_unlock( &avc_mutex );
01087     return 0;
01088 }
01089 
01090 int AVC::Record( int phyID )
01091 {
01092     pthread_mutex_lock( &avc_mutex );
01093     if ( avc_handle != NULL )
01094     {
01095         if ( phyID >= 0 )
01096             avc1394_vcr_record( avc_handle, phyID );
01097     }
01098     pthread_mutex_unlock( &avc_mutex );
01099     return 0;
01100 }
01101 
01102 int AVC::Shuttle( int phyID, int speed )
01103 {
01104     pthread_mutex_lock( &avc_mutex );
01105     if ( avc_handle != NULL )
01106     {
01107         if ( phyID >= 0 )
01108             avc1394_vcr_trick_play( avc_handle, phyID, speed );
01109     }
01110     pthread_mutex_unlock( &avc_mutex );
01111     return 0;
01112 }
01113 
01114 unsigned int AVC::TransportStatus( int phyID )
01115 {
01116     quadlet_t val = 0;
01117     pthread_mutex_lock( &avc_mutex );
01118     if ( avc_handle != NULL )
01119     {
01120         if ( phyID >= 0 )
01121             val = avc1394_vcr_status( avc_handle, phyID );
01122     }
01123     pthread_mutex_unlock( &avc_mutex );
01124     return val;
01125 }
01126 
01127 bool AVC::Timecode( int phyID, char* timecode )
01128 {
01129     pthread_mutex_lock( &avc_mutex );
01130     if ( avc_handle != NULL )
01131     {
01132         if ( phyID >= 0 )
01133         {
01134             quadlet_t request[ 2 ];
01135             quadlet_t *response;
01136 
01137             request[ 0 ] = AVC1394_CTYPE_STATUS | AVC1394_SUBUNIT_TYPE_TAPE_RECORDER | AVC1394_SUBUNIT_ID_0 |
01138                            AVC1394_VCR_COMMAND_TIME_CODE | AVC1394_VCR_OPERAND_TIME_CODE_STATUS;
01139             request[ 1 ] = 0xFFFFFFFF;
01140             response = avc1394_transaction_block( avc_handle, phyID, request, 2, 1 );
01141             if ( response == NULL )
01142             {
01143                 pthread_mutex_unlock( &avc_mutex );
01144                 return false;
01145             }
01146             if ( response[1] == 0xffffffff )
01147                 strcpy( timecode, "--:--:--:--" );
01148             else
01149                 sprintf( timecode, "%2.2x:%2.2x:%2.2x:%2.2x",
01150                      response[ 1 ] & 0x000000ff,
01151                      ( response[ 1 ] >> 8 ) & 0x000000ff,
01152                      ( response[ 1 ] >> 16 ) & 0x000000ff,
01153                      ( response[ 1 ] >> 24 ) & 0x000000ff );
01154         }
01155 
01156     }
01157     pthread_mutex_unlock( &avc_mutex );
01158     return true;
01159 }
01160 
01161 int AVC::getNodeId( const char *guid )
01162 {
01163     int value = -1;
01164     pthread_mutex_lock( &avc_mutex );
01165     if ( avc_handle != NULL )
01166     {
01167         raw1394_destroy_handle( avc_handle );
01168         avc_handle = NULL;
01169     }
01170     port = 0;
01171     for ( int p = 0; value == -1 && p < totalPorts; p++ )
01172     {
01173         rom1394_directory rom1394_dir;
01174         
01175         if ( ( avc_handle = raw1394_new_handle_on_port( p ) ) )
01176         {
01177             int nodeCount = raw1394_get_nodecount( avc_handle );
01178 
01179             port = p;
01180             raw1394_set_bus_reset_handler( avc_handle, this->ResetHandler );
01181 
01182             for ( int currentNode = 0; value == -1 && currentNode < nodeCount; currentNode++ )
01183             {
01184                 if ( rom1394_get_directory( avc_handle, currentNode, &rom1394_dir ) >= 0 )
01185                 {
01186                     octlet_t currentGUID = rom1394_get_guid( avc_handle, currentNode );
01187                     char currentGUIDStr[ 65 ];
01188                     snprintf( currentGUIDStr, 64, "%08x%08x", ( quadlet_t ) ( currentGUID >> 32 ),
01189                         ( quadlet_t ) ( currentGUID & 0xffffffff ) );
01190                     if ( strncmp( currentGUIDStr, guid, 64 ) == 0 )
01191                         value = currentNode;
01192                     rom1394_free_directory( &rom1394_dir );
01193                 }
01194             }
01195             if ( value == -1 )
01196             {
01197                 raw1394_destroy_handle( avc_handle );
01198                 avc_handle = NULL;
01199             }
01200         }
01201     }
01202     if ( value == -1 )
01203         port = -1;
01204     pthread_mutex_unlock( &avc_mutex );
01205     return value;
01206 }
01207 
01208 
01209 
01210 IEEE1394Writer::IEEE1394Writer() :
01211         m_isInitialised( false ), m_isRunning( false )
01212 {
01213     pthread_mutex_init( &m_dequeMutex, NULL );
01214     pthread_mutex_init( &m_conditionMutex, NULL );
01215     pthread_cond_init( &m_condition, NULL );
01216 }
01217 
01218 IEEE1394Writer::~IEEE1394Writer()
01219 {
01220     for ( int i = m_deque.size(); i > 0; --i )
01221     {
01222         Frame* frame = m_deque[ 0 ];
01223         m_deque.pop_front();
01224         GetFramePool()->DoneWithFrame( frame );
01225     }
01226     pthread_mutex_destroy( &m_conditionMutex );
01227     pthread_cond_destroy( &m_condition );
01228     pthread_mutex_destroy( &m_dequeMutex );
01229 }
01230 
01231 void IEEE1394Writer::StartThread()
01232 {
01233     if ( m_isRunning )
01234         return;
01235     pthread_create( &m_thread, NULL, ThreadProxy, this );
01236 }
01237 
01238 void IEEE1394Writer::StopThread()
01239 {
01240     if ( m_isRunning )
01241     {
01242         m_isRunning = false;
01243         pthread_join( m_thread, NULL );
01244     }
01245 }
01246 
01247 int IEEE1394Writer::WaitForAction( bool isBlocking, int seconds )
01248 {
01249     pthread_mutex_lock( &m_dequeMutex );
01250     int size = m_deque.size( );
01251     pthread_mutex_unlock( &m_dequeMutex );
01252 
01253     if ( ( unsigned int )size >= m_nBuffers )
01254     {
01255         if ( isBlocking )
01256         {
01257             pthread_mutex_lock( &m_conditionMutex );
01258             if ( seconds == 0 )
01259             {
01260                 pthread_cond_wait( &m_condition, &m_conditionMutex );
01261                 pthread_mutex_unlock( &m_conditionMutex );
01262                 pthread_mutex_lock( &m_dequeMutex );
01263                 size = m_deque.size( );
01264             }
01265             else
01266             {
01267                 struct timeval tp;
01268                 struct timespec ts;
01269                 int result;
01270     
01271                 gettimeofday( &tp, NULL );
01272                 ts.tv_sec = tp.tv_sec + seconds;
01273                 ts.tv_nsec = tp.tv_usec * 1000;
01274     
01275                 result = pthread_cond_timedwait( &m_condition, &m_conditionMutex, &ts );
01276                 pthread_mutex_unlock( &m_conditionMutex );
01277                 pthread_mutex_lock( &m_dequeMutex );
01278     
01279                 size = m_deque.size();
01280                 if ( ( unsigned int )size >= m_nBuffers )
01281                     size = -size;
01282             }
01283             pthread_mutex_unlock( &m_dequeMutex );
01284         }
01285         else
01286         {
01287             size = -size;
01288         }
01289     }
01290 
01291     return size;
01292 }
01293 
01294 void IEEE1394Writer::TriggerAction( )
01295 {
01296     pthread_mutex_lock( &m_conditionMutex );
01297     pthread_cond_signal( &m_condition );
01298     pthread_mutex_unlock( &m_conditionMutex );
01299 }
01300 
01301 void* IEEE1394Writer::ThreadProxy( void *arg )
01302 {
01303     IEEE1394Writer* self = static_cast< IEEE1394Writer* >( arg );
01304     return self->Thread();
01305 }
01306 
01307 
01308 #ifdef HAVE_IEC61883
01309 iec61883Writer::iec61883Writer( int port, unsigned int channel, unsigned int buffers )
01310     : m_port( port ), m_handle( NULL ), m_iec61883dv( NULL ),
01311     m_data( 0 ), m_index( -1 ), m_isSilent( false ), m_isReset( false )
01312 {
01313     cerr << ">>> iec61883Writer::iec61883Writer port " << port << " channel " << channel << endl;
01314     m_channel = channel;
01315     m_nBuffers = buffers;
01316 }
01317 
01318 iec61883Writer::~iec61883Writer()
01319 {
01320     // signal SendFrame to not accept incoming frame
01321     TriggerAction();
01322     m_isReset = true;
01323 
01324     StopThread();
01325 
01326     if ( m_iec61883dv )
01327     {
01328         iec61883_dv_close( m_iec61883dv );
01329         raw1394_destroy_handle( m_handle );
01330     }
01331 }
01332 
01333 
01334 int iec61883Writer::HandlerProxy( unsigned char *data, int n_dif_blocks,
01335     unsigned int dropped, void *callback_data)
01336 {
01337     if ( callback_data )
01338     {
01339         iec61883Writer* writer = static_cast< iec61883Writer* >( callback_data );
01340         return writer->Handler( data, n_dif_blocks, dropped );
01341     }
01342     else
01343     {
01344         return -1;
01345     }
01346 }
01347 
01348 
01349 int iec61883Writer::Handler( unsigned char *data, int n_dif_blocks, unsigned int dropped )
01350 {
01351     // Initialize or reset current frame
01352     if ( m_index <= 0 )
01353     {
01354         // Cancel thread by telling raw1394_iso to end
01355         // It is important for reliability of next transmission in the same
01356         // process that this occurs on a frame boundary!
01357         if ( !m_isRunning || m_isReset )
01358             return -1;
01359 
01360         pthread_mutex_lock( &m_dequeMutex );
01361         Frame* frame = m_deque[0];
01362         pthread_mutex_unlock( &m_dequeMutex );
01363 
01364         m_data = frame->data;
01365         m_index = frame->GetFrameSize();
01366     }
01367 
01368     // Transfer the DV data to FireWire
01369     memcpy( data, m_data, n_dif_blocks * 480 );
01370 
01371     // Move data cursor
01372     m_data += n_dif_blocks * 480;
01373     m_index -= n_dif_blocks * 480;
01374 
01375     // When we have sent all of the current frame
01376     if ( m_index == 0 )
01377     {
01378         pthread_mutex_lock( &m_dequeMutex );
01379         Frame* frame = m_deque[0];
01380         if ( m_deque.size() > 1 )
01381         {
01382             // Discard the current frame only if more than one available
01383             m_deque.pop_front();
01384             GetFramePool()->DoneWithFrame( frame );
01385 
01386             // Awaken a blocked parent thread
01387             TriggerAction();
01388 
01389             // frontmost frame has changed so we need to silence it if repeated
01390             m_isSilent = false;
01391         }
01392         else if ( !m_isSilent )
01393         {
01394             AudioInfo info;
01395             int16_t* silence[4];
01396 
01397             // Make the repeated frame silent to avoid annoyance
01398             for ( int i = 0; i < 4; i++ )
01399                 silence[i] = (int16_t*) calloc( 2 * DV_AUDIO_MAX_SAMPLES, sizeof( int16_t ) );
01400             frame->GetAudioInfo( info );
01401             info.channels = 2;
01402             frame->EncodeAudio( info, silence );
01403             for ( int i = 0; i < 4; i++ )
01404                 free( silence[i] );
01405 
01406             // Do not need to silence this frame again
01407             m_isSilent = true;
01408         }
01409         pthread_mutex_unlock( &m_dequeMutex );
01410     }
01411 
01412     return 0;
01413 }
01414 
01415 bool iec61883Writer::Open( bool isPAL )
01416 {
01417     assert( m_handle == 0 );
01418     m_isInitialised = false;
01419     m_handle = raw1394_new_handle_on_port( m_port );
01420     if ( m_handle != NULL )
01421     {
01422         raw1394_set_bus_reset_handler( m_handle, this->ResetHandlerProxy );
01423         m_iec61883dv = iec61883_dv_xmit_init( m_handle, isPAL, HandlerProxy, this );
01424         m_isInitialised = ( m_iec61883dv != NULL );
01425         //iec61883_dv_set_synch( m_iec61883dv, 1 ); this is causing hang on close
01426     }
01427 
01428     return m_isInitialised;
01429 }
01430 
01431 bool iec61883Writer::SendFrame( Frame &frame, bool isBlocking )
01432 {
01433     bool result = false;
01434 
01435     if ( m_isReset )
01436     {
01437         StopThread();
01438         if ( m_iec61883dv )
01439         {
01440             // iec61883_dv_close( m_iec61883dv ) hangs here
01441             free( m_iec61883dv );
01442             m_iec61883dv = NULL;
01443         }
01444         raw1394_destroy_handle( m_handle );
01445         m_handle = NULL;
01446         m_isInitialised = m_isReset = false;
01447     }
01448 
01449     // Block if too full
01450     if ( WaitForAction( isBlocking ) >= 0 )
01451     {
01452         // Duplicate the frame
01453         Frame *newFrame = GetFramePool()->GetFrame();
01454         *newFrame = frame;
01455     
01456         pthread_mutex_lock( &m_dequeMutex );
01457         m_deque.push_back( newFrame );
01458         pthread_mutex_unlock( &m_dequeMutex );
01459     
01460         if ( !m_isInitialised && Open( frame.IsPAL() ) )
01461         {
01462             m_isInitialised = ( iec61883_dv_xmit_start( m_iec61883dv, m_channel ) == 0 );
01463             StartThread();
01464         }
01465         result = true;
01466     }
01467     return result;
01468 }
01469 
01470 void* iec61883Writer::Thread()
01471 {
01472     // poll raw1394
01473     struct pollfd pfd = {
01474         fd: raw1394_get_fd( m_handle ),
01475         events: POLLIN,
01476         revents: 0
01477     };
01478     int result = 0;
01479 
01480     m_isRunning = true;
01481     while ( !m_isReset && result == 0 )
01482     {
01483         if ( poll( &pfd, 1, 100 ) > 0 && ( pfd.revents & POLLIN ) )
01484             result = raw1394_loop_iterate( m_handle );
01485     }
01486 
01487     return NULL;
01488 }
01489 
01490 void iec61883Writer::ResetHandler( void )
01491 {
01492     cerr << ">>> iec61883Writer::ResetHandler" << endl;
01493     if ( m_isInitialised )
01494         m_isReset = true;
01495 }
01496 
01497 int iec61883Writer::ResetHandlerProxy( raw1394handle_t handle, unsigned int generation )
01498 {
01499     iec61883_dv_t dv = static_cast< iec61883_dv_t >( raw1394_get_userdata( handle ) );
01500     iec61883Writer *self = static_cast< iec61883Writer* >( iec61883_dv_get_callback_data( dv ) );
01501     raw1394_update_generation( handle, generation );
01502     if ( self )
01503         self->ResetHandler();
01504     return 0;
01505 }
01506 #endif
01507 
01508 
01509 #ifdef HAVE_DV1394
01510 dv1394Writer::dv1394Writer( string device, unsigned int channel, unsigned int nBuffers,
01511                             unsigned int cip_n, unsigned int cip_d, unsigned int syt_offset )
01512     : m_channel( channel ), m_cip_n( cip_n ), m_cip_d( cip_d ), m_syt_offset( syt_offset ),
01513       m_isSilent( false )
01514 {
01515     m_nBuffers = ( nBuffers > DV1394_MAX_FRAMES ) ? DV1394_MAX_FRAMES : nBuffers;
01516     m_fd = open( device.c_str(), O_RDWR );
01517     cerr << ">>> dv1394Writer::dv1394Writer " << device << " channel " << m_channel << " fd " << m_fd << endl;
01518 }
01519 
01520 
01521 dv1394Writer::~dv1394Writer()
01522 {
01523     StopThread();
01524     if ( m_fd != -1 )
01525     {
01526         close( m_fd );
01527         m_fd = -1;
01528     }
01529 }
01530 
01531 
01532 bool dv1394Writer::SendFrame( Frame &frame, bool isBlocking )
01533 {
01534     bool result = false;
01535 
01536     if ( m_fd < 0 )
01537         return result;
01538 
01539     bool isPAL = frame.IsPAL();
01540 
01541     // Block if too full
01542     if ( WaitForAction( isBlocking ) >= 0 )
01543     {
01544         // Duplicate the frame
01545         Frame *newFrame = GetFramePool()->GetFrame();
01546         *newFrame = frame;
01547     
01548         pthread_mutex_lock( &m_dequeMutex );
01549         m_deque.push_back( newFrame );
01550         pthread_mutex_unlock( &m_dequeMutex );
01551     
01552         if ( !m_isInitialised )
01553         {
01554             m_isInitialised = true;
01555     
01556             struct dv1394_init setup =
01557                 {
01558                 api_version: DV1394_API_VERSION,
01559                 channel: m_channel,
01560                 n_frames: m_nBuffers,
01561                 format: ( isPAL ? DV1394_PAL : DV1394_NTSC ),
01562                 cip_n : m_cip_n,
01563                 cip_d : m_cip_d,
01564                 syt_offset : m_syt_offset
01565                 };
01566             ioctl( m_fd, DV1394_INIT, &setup );
01567             StartThread();
01568         }
01569         result = true;
01570     }
01571     return result;
01572 }
01573 
01574 void* dv1394Writer::Thread()
01575 {
01576     m_isRunning = true;
01577     while ( m_isRunning )
01578     {
01579         Frame* frame = m_deque[0];
01580 
01581         if ( frame )
01582             write( m_fd, frame->data, ( frame->IsPAL() ? DV1394_PAL_FRAME_SIZE : DV1394_NTSC_FRAME_SIZE ) );
01583 
01584         pthread_mutex_lock( &m_dequeMutex );
01585         if ( m_deque.size() > 1 )
01586         {
01587             // Discard the current frame only if more than one available
01588             m_deque.pop_front();
01589             GetFramePool()->DoneWithFrame( frame );
01590 
01591             // Awaken a blocked parent thread
01592             TriggerAction();
01593 
01594             // frontmost frame has changed so we need to silence it if repeated
01595             m_isSilent = false;
01596         }
01597         else if ( !m_isSilent )
01598         {
01599             AudioInfo info;
01600             int16_t* silence[4];
01601 
01602             // Make the repeated frame silent to avoid annoyance
01603             for ( int i = 0; i < 4; i++ )
01604                 silence[i] = (int16_t*) calloc( 2 * DV_AUDIO_MAX_SAMPLES, sizeof( int16_t ) );
01605             frame->GetAudioInfo( info );
01606             info.channels = 2;
01607             frame->EncodeAudio( info, silence );
01608             for ( int i = 0; i < 4; i++ )
01609                 free( silence[i] );
01610 
01611             // Do not need to silence this frame again
01612             m_isSilent = true;
01613         }
01614         pthread_mutex_unlock( &m_dequeMutex );
01615     }
01616 
01617     return NULL;
01618 }
01619 #endif

Generated on Sun Mar 11 22:11:45 2007 for Kino by  doxygen 1.4.2