Changeset 244

Show
Ignore:
Timestamp:
06/05/06 01:13:34 (16 years ago)
Author:
pieterpalmers
Message:

- first try to implement the SYT synchronisation.

Not working yet.

- committing to spend some time to get the Motu people going.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/libfreebob-2.0/src/debugmodule/debugmodule.h

    r242 r244  
    3131 
    3232/* MB_NEXT() relies on the fact that MB_BUFFERS is a power of two */ 
    33 #define MB_BUFFERS      1024 
     33#define MB_BUFFERS      4096 
    3434#define MB_NEXT(index) ((index+1) & (MB_BUFFERS-1)) 
    3535#define MB_BUFFERSIZE   256             /* message length limit */ 
  • branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.cpp

    r242 r244  
    3434#include <assert.h> 
    3535 
     36#define CYCLE_COUNTER_GET_SECS(x)   (((x & 0xFE000000) >> 25)) 
     37#define CYCLE_COUNTER_GET_CYCLES(x) (((x & 0x01FFF000) >> 12)) 
     38#define CYCLE_COUNTER_GET_TICKS(x)  (((x & 0x00000FFF))) 
     39#define CYCLE_COUNTER_TO_TICKS(x) ((CYCLE_COUNTER_GET_SECS(x)   * 24576000) +\ 
     40                                   (CYCLE_COUNTER_GET_CYCLES(x) *     3072) +\ 
     41                                   (CYCLE_COUNTER_GET_TICKS(x)            )) 
     42 
     43// this is one milisecond of processing delay 
     44#define TICKS_PER_SECOND 24576000 
     45#define RECEIVE_PROCESSING_DELAY (TICKS_PER_SECOND / 500) 
    3646 
    3747namespace FreebobStreaming { 
     
    7484 
    7585 
    76 int AmdtpTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length, 
     86enum raw1394_iso_disposition 
     87AmdtpTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length, 
    7788                      unsigned char *tag, unsigned char *sy, 
    7889                      int cycle, unsigned int dropped, unsigned int max_length) { 
    7990 
    8091        struct iec61883_packet *packet = (struct iec61883_packet *) data; 
     92         
    8193         
    8294        // signal that we are running (a transmit stream is always 'runnable') 
     
    91103                *tag = IEC61883_TAG_WITH_CIP; 
    92104                *sy = 0; 
    93                 return (int)RAW1394_ISO_OK; 
     105                return RAW1394_ISO_OK; 
    94106        } 
     107         
     108     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); 
     109         
     110        // keep the old cip, in case we don't have enough events left in the buffer. 
     111        struct iec61883_cip old_cip; 
     112        memcpy(&old_cip,&m_cip_status,sizeof(struct iec61883_cip)); 
    95113                 
    96114        // construct the packet cip 
     
    103121                if (m_cip_status.mode == IEC61883_MODE_BLOCKING_EMPTY) { 
    104122                        *length = 8; 
    105                         return (int)RAW1394_ISO_OK ; 
     123                        return RAW1394_ISO_OK ; 
    106124                } 
    107125                else { 
     
    115133                                read_size)  
    116134        { 
    117                 debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",  
    118                              cycle, m_framecounter, m_handler->getPacketCount()); 
    119                  
    120                 // signal underrun 
    121                 m_xruns++; 
    122  
    123                 retval=RAW1394_ISO_DEFER; 
    124                 *length=0; 
    125  
    126         } else { 
    127                 retval=RAW1394_ISO_OK; 
    128                 *length = read_size + 8; 
    129                  
    130                 // process all ports that should be handled on a per-packet base 
    131                 // this is MIDI for AMDTP (due to the need of DBC) 
    132                 if (!encodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) { 
    133                         debugWarning("Problem encoding Packet Ports\n"); 
    134                 } 
    135         } 
    136          
    137         *tag = IEC61883_TAG_WITH_CIP; 
    138         *sy = 0; 
    139          
    140         // update the frame counter 
    141         m_framecounter+=nevents; 
     135        /* there is no more data in the ringbuffer */ 
     136         
     137        /* If there are already more than on period 
     138        * of frames transfered to the XMIT buffer, there is no xrun. 
     139        *  
     140        */ 
     141        if(m_framecounter>m_period) { 
     142            // we stop processing this untill the next period boundary 
     143            // that's when new data is ready 
     144             
     145            //connection->pfd->events=0; 
     146             
     147            // reset the cip to the old value 
     148            memcpy(&m_cip_status,&old_cip,sizeof(struct iec61883_cip)); 
     149 
     150            // retry this packed  
     151            retval=RAW1394_ISO_AGAIN; 
     152            nevents=0; 
     153            debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "again!\n"); 
     154             
     155        } else { 
     156            debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",  
     157                     cycle, m_framecounter, m_handler->getPacketCount()); 
     158             
     159            // signal underrun 
     160            m_xruns++; 
     161     
     162            retval=RAW1394_ISO_DEFER; 
     163            *length=0; 
     164            nevents=0; 
     165        } 
     166 
     167    } else { 
     168        retval=RAW1394_ISO_OK; 
     169        *length = read_size + 8; 
     170         
     171        // process all ports that should be handled on a per-packet base 
     172        // this is MIDI for AMDTP (due to the need of DBC) 
     173        if (!encodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) { 
     174            debugWarning("Problem encoding Packet Ports\n"); 
     175        } 
     176         
     177        if (packet->syt != 0xFFFF) { 
     178             unsigned int m_last_timestamp=ntohs(packet->syt); 
     179             // reconstruct the top part of the timestamp using the current cycle number 
     180              m_last_timestamp |= ((cycle << 12) & 0x01FF0000); 
     181              
     182             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Sent packet with SYT for cycle %2d: %5u ticks (%2u cycles + %04u ticks)\n", 
     183             cycle, 
     184             CYCLE_COUNTER_TO_TICKS(m_last_timestamp), 
     185             CYCLE_COUNTER_GET_CYCLES(m_last_timestamp), 
     186             CYCLE_COUNTER_GET_TICKS(m_last_timestamp) 
     187             ); 
     188        } 
     189    } 
     190     
     191    *tag = IEC61883_TAG_WITH_CIP; 
     192    *sy = 0; 
     193     
     194    // update the frame counter 
     195    m_framecounter+=nevents; 
    142196    if(m_framecounter>m_period) { 
    143197       retval=RAW1394_ISO_DEFER; 
     
    145199     
    146200    m_PacketStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    147  
    148         return (int)retval; 
    149  
     201         
     202    return retval; 
     203 
     204
     205 
     206bool AmdtpTransmitStreamProcessor::isOnePeriodReady() 
     207{  
     208    //return true; 
     209     return (m_framecounter > (int)m_period);  
     210
     211  
     212bool AmdtpTransmitStreamProcessor::prefill() { 
     213    int i=m_nb_buffers; 
     214    while(i--) { 
     215        if(!transferSilence(m_period)) { 
     216            debugFatal("Could not prefill transmit stream\n"); 
     217            return false; 
     218        } 
     219    } 
     220     
     221    // and we should also provide enough prefill for the 
     222    // SYT processing delay 
     223/*    if(!transferSilence((m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND)) { 
     224        debugFatal("Could not prefill transmit stream\n"); 
     225        return false; 
     226    }*/ 
     227     
     228    // the framecounter should be pulled back to 
     229    // make sure the ISO buffering is used  
     230    // we are using 1 period of iso buffering 
     231//     m_framecounter=-m_period; 
     232     
     233    // should this also be pre-buffered? 
     234    //m_framecounter=-(m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND; 
     235     
     236    return true; 
     237     
    150238} 
    151239 
    152240bool AmdtpTransmitStreamProcessor::reset() { 
    153241 
    154         debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n"); 
    155  
    156         // reset the event buffer, discard all content 
    157         freebob_ringbuffer_reset(m_event_buffer); 
    158          
    159         // we should prefill the event buffer 
    160         int i=m_nb_buffers; 
    161         while(i--) { 
    162                 if(!transferSilence()) { 
    163                         debugFatal("Could not prefill transmit stream\n"); 
    164                         return false; 
    165                 } 
    166         } 
    167          
    168         // reset all non-device specific stuff 
    169         // i.e. the iso stream and the associated ports 
    170         if(!TransmitStreamProcessor::reset()) { 
    171                 debugFatal("Could not do base class reset\n"); 
    172                 return false; 
    173         } 
    174         return true; 
     242    debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n"); 
     243 
     244    // reset the event buffer, discard all content 
     245    freebob_ringbuffer_reset(m_event_buffer); 
     246     
     247    // reset the statistics 
     248        m_PeriodStat.reset(); 
     249    m_PacketStat.reset(); 
     250    m_WakeupStat.reset(); 
     251     
     252    // reset all non-device specific stuff 
     253    // i.e. the iso stream and the associated ports 
     254    if(!TransmitStreamProcessor::reset()) { 
     255        debugFatal("Could not do base class reset\n"); 
     256        return false; 
     257    } 
     258     
     259    // we should prefill the event buffer 
     260    if (!prefill()) { 
     261        debugFatal("Could not prefill buffers\n"); 
     262        return false;     
     263    } 
     264     
     265    return true; 
    175266} 
    176267 
     
    180271    m_WakeupStat.setName("XMT WAKEUP"); 
    181272 
    182         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n"); 
    183          
    184         // prepare all non-device specific stuff 
    185         // i.e. the iso stream and the associated ports 
    186         if(!TransmitStreamProcessor::prepare()) { 
    187                 debugFatal("Could not prepare base class\n"); 
    188                 return false; 
    189         } 
    190          
    191         switch (m_framerate) { 
    192         case 32000: 
    193                 m_syt_interval = 8; 
    194                 m_fdf = IEC61883_FDF_SFC_32KHZ; 
    195                 break; 
    196         case 44100: 
    197                 m_syt_interval = 8; 
    198                 m_fdf = IEC61883_FDF_SFC_44K1HZ; 
    199                 break; 
    200         default: 
    201         case 48000: 
    202                 m_syt_interval = 8; 
    203                 m_fdf = IEC61883_FDF_SFC_48KHZ; 
    204                 break; 
    205         case 88200: 
    206                 m_syt_interval = 16; 
    207                 m_fdf = IEC61883_FDF_SFC_88K2HZ; 
    208                 break; 
    209         case 96000: 
    210                 m_syt_interval = 16; 
    211                 m_fdf = IEC61883_FDF_SFC_96KHZ; 
    212                 break; 
    213         case 176400: 
    214                 m_syt_interval = 32; 
    215                 m_fdf = IEC61883_FDF_SFC_176K4HZ; 
    216                 break; 
    217         case 192000: 
    218                 m_syt_interval = 32; 
    219                 m_fdf = IEC61883_FDF_SFC_192KHZ; 
    220                 break; 
    221         } 
    222          
    223         iec61883_cip_init ( 
    224                 &m_cip_status,  
    225                 IEC61883_FMT_AMDTP,  
    226                 m_fdf, 
    227                 m_framerate,  
    228                 m_dimension,  
    229                 m_syt_interval); 
    230  
    231         // allocate the event buffer 
    232         if( !(m_event_buffer=freebob_ringbuffer_create( 
    233                         (m_dimension * m_nb_buffers * m_period) * sizeof(quadlet_t)))) { 
    234                 debugFatal("Could not allocate memory event ringbuffer"); 
     273    debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n"); 
     274     
     275    // prepare all non-device specific stuff 
     276    // i.e. the iso stream and the associated ports 
     277    if(!TransmitStreamProcessor::prepare()) { 
     278        debugFatal("Could not prepare base class\n"); 
     279        return false; 
     280    } 
     281     
     282    switch (m_framerate) { 
     283    case 32000: 
     284        m_syt_interval = 8; 
     285        m_fdf = IEC61883_FDF_SFC_32KHZ; 
     286        break; 
     287    case 44100: 
     288        m_syt_interval = 8; 
     289        m_fdf = IEC61883_FDF_SFC_44K1HZ; 
     290        break; 
     291    default: 
     292    case 48000: 
     293        m_syt_interval = 8; 
     294        m_fdf = IEC61883_FDF_SFC_48KHZ; 
     295        break; 
     296    case 88200: 
     297        m_syt_interval = 16; 
     298        m_fdf = IEC61883_FDF_SFC_88K2HZ; 
     299        break; 
     300    case 96000: 
     301        m_syt_interval = 16; 
     302        m_fdf = IEC61883_FDF_SFC_96KHZ; 
     303        break; 
     304    case 176400: 
     305        m_syt_interval = 32; 
     306        m_fdf = IEC61883_FDF_SFC_176K4HZ; 
     307        break; 
     308    case 192000: 
     309        m_syt_interval = 32; 
     310        m_fdf = IEC61883_FDF_SFC_192KHZ; 
     311        break; 
     312    } 
     313     
     314    iec61883_cip_init ( 
     315        &m_cip_status,  
     316        IEC61883_FMT_AMDTP,  
     317        m_fdf, 
     318        m_framerate,  
     319        m_dimension,  
     320        m_syt_interval); 
     321 
     322    // allocate the event buffer 
     323    unsigned int ringbuffer_size_frames=m_nb_buffers * m_period; 
     324     
     325    // add the processing delay 
     326    ringbuffer_size_frames+=(m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND; 
     327     
     328    if( !(m_event_buffer=freebob_ringbuffer_create( 
     329            (m_dimension * ringbuffer_size_frames) * sizeof(quadlet_t)))) { 
     330        debugFatal("Could not allocate memory event ringbuffer"); 
    235331//              return -ENOMEM; 
    236                return false; 
    237        
    238  
    239        // allocate the temporary cluster buffer 
    240        if( !(m_cluster_buffer=(char *)calloc(m_dimension,sizeof(quadlet_t)))) { 
    241                debugFatal("Could not allocate temporary cluster buffer"); 
    242                freebob_ringbuffer_free(m_event_buffer); 
    243                return false; 
     332        return false; 
     333   
     334 
     335    // allocate the temporary cluster buffer 
     336    if( !(m_cluster_buffer=(char *)calloc(m_dimension,sizeof(quadlet_t)))) { 
     337        debugFatal("Could not allocate temporary cluster buffer"); 
     338        freebob_ringbuffer_free(m_event_buffer); 
     339        return false; 
    244340//              return -ENOMEM; 
    245        
    246  
    247        // set the parameters of ports we can: 
    248        // we want the audio ports to be period buffered, 
    249        // and the midi ports to be packet buffered 
    250        for ( PortVectorIterator it = m_Ports.begin(); 
    251                  it != m_Ports.end(); 
    252                  ++it ) 
    253        
    254                debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
    255                if(!(*it)->setBufferSize(m_period)) { 
    256                        debugFatal("Could not set buffer size to %d\n",m_period); 
    257                        return false; 
    258                
    259                  
    260                  
    261                switch ((*it)->getPortType()) { 
    262                        case Port::E_Audio: 
    263                                if(!(*it)->setSignalType(Port::E_PeriodSignalled)) { 
    264                                        debugFatal("Could not set signal type to PeriodSignalling"); 
    265                                        return false; 
    266                                
    267                                debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); 
    268                                // buffertype and datatype are dependant on the API 
    269                                if(!(*it)->setBufferType(Port::E_PointerBuffer)) { 
    270                                        debugFatal("Could not set buffer type"); 
    271                                        return false; 
    272                                
    273                                if(!(*it)->useExternalBuffer(true)) { 
    274                                        debugFatal("Could not set external buffer usage"); 
    275                                        return false; 
    276                                
    277                                  
    278                                if(!(*it)->setDataType(Port::E_Float)) { 
    279                                        debugFatal("Could not set data type"); 
    280                                        return false; 
    281                                
    282                                  
    283                                  
    284                                break; 
    285                        case Port::E_Midi: 
    286                                if(!(*it)->setSignalType(Port::E_PacketSignalled)) { 
    287                                        debugFatal("Could not set signal type to PeriodSignalling"); 
    288                                        return false; 
    289                                
    290                                  
    291                                // we use a timing unit of 10ns 
    292                                // this makes sure that for the max syt interval 
    293                                // we don't have rounding, and keeps the numbers low 
    294                                // we have 1 slot every 8 events 
    295                                // we have syt_interval events per packet 
    296                                // => syt_interval/8 slots per packet 
    297                                // packet rate is 8000pkt/sec => interval=125us 
    298                                // so the slot interval is (1/8000)/(syt_interval/8) 
    299                                // or: 1/(1000 * syt_interval) sec 
    300                                // which is 1e9/(1000*syt_interval) nsec 
    301                                // or 100000/syt_interval 'units' 
    302                                // the event interval is fixed to 320us = 32000 'units' 
    303                                if(!(*it)->useRateControl(true,(100000/m_syt_interval),32000, false)) { 
    304                                        debugFatal("Could not set signal type to PeriodSignalling"); 
    305                                        return false; 
    306                                
    307                                  
    308                                // buffertype and datatype are dependant on the API 
    309                                debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); 
    310                                // buffertype and datatype are dependant on the API 
    311                                if(!(*it)->setBufferType(Port::E_RingBuffer)) { 
    312                                        debugFatal("Could not set buffer type"); 
    313                                        return false; 
    314                                
    315                                if(!(*it)->setDataType(Port::E_MidiEvent)) { 
    316                                        debugFatal("Could not set data type"); 
    317                                        return false; 
    318                                
    319                                break; 
    320                        default: 
    321                                debugWarning("Unsupported port type specified\n"); 
    322                                break; 
    323                
    324        
    325  
    326        // the API specific settings of the ports should already be set,  
    327        // as this is called from the processorManager->prepare() 
    328        // so we can init the ports 
    329        if(!initPorts()) { 
    330                debugFatal("Could not initialize ports!\n"); 
    331                return false; 
    332        
    333  
    334        if(!preparePorts()) { 
    335                debugFatal("Could not initialize ports!\n"); 
    336                return false; 
    337        
    338  
    339        // we should prefill the event buffer 
    340         int i=m_nb_buffers; 
    341         while(i--) { 
    342                 if(!transferSilence()) { 
    343                         debugFatal("Could not prefill transmit stream\n"); 
    344                         return false; 
    345                 } 
    346         } 
    347          
    348         debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n"); 
    349         debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, FDF: %d, DBS: %d, SYT: %d\n", 
    350                      m_framerate,m_fdf,m_dimension,m_syt_interval); 
    351         debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n", 
    352                      m_period,m_nb_buffers); 
    353         debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n", 
    354                      m_port,m_channel); 
    355  
    356         return true; 
    357  
    358 
    359  
    360 bool AmdtpTransmitStreamProcessor::transferSilence() { 
    361         /* a naive implementation would look like this: */ 
    362          
    363         unsigned int write_size=m_period*sizeof(quadlet_t)*m_dimension; 
    364         char *dummybuffer=(char *)calloc(sizeof(quadlet_t),m_period*m_dimension); 
    365        transmitSilenceBlock(dummybuffer, m_period, 0); 
    366  
    367         if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
    368                debugWarning("Could not write to event buffer\n"); 
    369         } 
    370        return true; 
     341   
     342 
     343    // set the parameters of ports we can: 
     344    // we want the audio ports to be period buffered, 
     345    // and the midi ports to be packet buffered 
     346    for ( PortVectorIterator it = m_Ports.begin(); 
     347          it != m_Ports.end(); 
     348          ++it ) 
     349   
     350        debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
     351        if(!(*it)->setBufferSize(m_period)) { 
     352            debugFatal("Could not set buffer size to %d\n",m_period); 
     353            return false; 
     354       
     355         
     356         
     357        switch ((*it)->getPortType()) { 
     358            case Port::E_Audio: 
     359                if(!(*it)->setSignalType(Port::E_PeriodSignalled)) { 
     360                    debugFatal("Could not set signal type to PeriodSignalling"); 
     361                    return false; 
     362               
     363                debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); 
     364                // buffertype and datatype are dependant on the API 
     365                if(!(*it)->setBufferType(Port::E_PointerBuffer)) { 
     366                    debugFatal("Could not set buffer type"); 
     367                    return false; 
     368               
     369                if(!(*it)->useExternalBuffer(true)) { 
     370                    debugFatal("Could not set external buffer usage"); 
     371                    return false; 
     372               
     373                 
     374                if(!(*it)->setDataType(Port::E_Float)) { 
     375                    debugFatal("Could not set data type"); 
     376                    return false; 
     377               
     378                 
     379                 
     380                break; 
     381            case Port::E_Midi: 
     382                if(!(*it)->setSignalType(Port::E_PacketSignalled)) { 
     383                    debugFatal("Could not set signal type to PeriodSignalling"); 
     384                    return false; 
     385               
     386                 
     387                // we use a timing unit of 10ns 
     388                // this makes sure that for the max syt interval 
     389                // we don't have rounding, and keeps the numbers low 
     390                // we have 1 slot every 8 events 
     391                // we have syt_interval events per packet 
     392                // => syt_interval/8 slots per packet 
     393                // packet rate is 8000pkt/sec => interval=125us 
     394                // so the slot interval is (1/8000)/(syt_interval/8) 
     395                // or: 1/(1000 * syt_interval) sec 
     396                // which is 1e9/(1000*syt_interval) nsec 
     397                // or 100000/syt_interval 'units' 
     398                // the event interval is fixed to 320us = 32000 'units' 
     399                if(!(*it)->useRateControl(true,(100000/m_syt_interval),32000, false)) { 
     400                    debugFatal("Could not set signal type to PeriodSignalling"); 
     401                    return false; 
     402               
     403                 
     404                // buffertype and datatype are dependant on the API 
     405                debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); 
     406                // buffertype and datatype are dependant on the API 
     407                if(!(*it)->setBufferType(Port::E_RingBuffer)) { 
     408                    debugFatal("Could not set buffer type"); 
     409                    return false; 
     410               
     411                if(!(*it)->setDataType(Port::E_MidiEvent)) { 
     412                    debugFatal("Could not set data type"); 
     413                    return false; 
     414               
     415                break; 
     416            default: 
     417                debugWarning("Unsupported port type specified\n"); 
     418                break; 
     419       
     420   
     421 
     422    // the API specific settings of the ports should already be set,  
     423    // as this is called from the processorManager->prepare() 
     424    // so we can init the ports 
     425    if(!initPorts()) { 
     426        debugFatal("Could not initialize ports!\n"); 
     427        return false; 
     428   
     429 
     430    if(!preparePorts()) { 
     431        debugFatal("Could not initialize ports!\n"); 
     432        return false; 
     433   
     434 
     435    // we should prefill the event buffer 
     436    if (!prefill()) { 
     437        debugFatal("Could not prefill buffers\n"); 
     438        return false;     
     439    } 
     440     
     441    debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n"); 
     442    debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, FDF: %d, DBS: %d, SYT: %d\n", 
     443             m_framerate,m_fdf,m_dimension,m_syt_interval); 
     444    debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n", 
     445             m_period,m_nb_buffers); 
     446    debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n", 
     447             m_port,m_channel); 
     448 
     449    return true; 
     450 
     451
     452 
     453bool AmdtpTransmitStreamProcessor::transferSilence(unsigned int size) { 
     454    /* a naive implementation would look like this: */ 
     455     
     456    unsigned int write_size=size*sizeof(quadlet_t)*m_dimension; 
     457    char *dummybuffer=(char *)calloc(sizeof(quadlet_t),size*m_dimension); 
     458    transmitSilenceBlock(dummybuffer, size, 0); 
     459 
     460    if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
     461        debugWarning("Could not write to event buffer\n"); 
     462    } 
     463     
     464    free(dummybuffer); 
     465     
     466    return true; 
    371467} 
    372468 
     
    374470    m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    375471 
    376        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
    377        // TODO: improve 
     472    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
     473    // TODO: improve 
    378474/* a naive implementation would look like this: 
    379475 
    380        unsigned int write_size=m_period*sizeof(quadlet_t)*m_dimension; 
    381        char *dummybuffer=(char *)calloc(sizeof(quadlet_t),m_period*m_dimension); 
    382        transmitBlock(dummybuffer, m_period, 0, 0); 
    383  
    384        if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
    385                debugWarning("Could not write to event buffer\n"); 
    386        
    387  
    388  
    389        free(dummybuffer); 
     476    unsigned int write_size=m_period*sizeof(quadlet_t)*m_dimension; 
     477    char *dummybuffer=(char *)calloc(sizeof(quadlet_t),m_period*m_dimension); 
     478    transmitBlock(dummybuffer, m_period, 0, 0); 
     479 
     480    if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
     481        debugWarning("Could not write to event buffer\n"); 
     482   
     483 
     484 
     485    free(dummybuffer); 
    390486*/ 
    391487/* but we're not that naive anymore... */ 
    392        int xrun; 
    393        unsigned int offset=0; 
    394          
    395        freebob_ringbuffer_data_t vec[2]; 
    396        // we received one period of frames 
    397        // this is period_size*dimension of events 
    398        int events2write=m_period*m_dimension; 
    399        int bytes2write=events2write*sizeof(quadlet_t); 
    400  
    401        /* write events2write bytes to the ringbuffer  
    402        *  first see if it can be done in one read. 
    403        *  if so, ok.  
    404        *  otherwise write up to a multiple of clusters directly to the buffer 
    405        *  then do the buffer wrap around using ringbuffer_write 
    406        *  then write the remaining data directly to the buffer in a third pass  
    407        *  Make sure that we cannot end up on a non-cluster aligned position! 
    408        */ 
    409        int cluster_size=m_dimension*sizeof(quadlet_t); 
    410  
    411        while(bytes2write>0) { 
    412                int byteswritten=0; 
    413                  
    414                unsigned int frameswritten=(m_period*cluster_size-bytes2write)/cluster_size; 
    415                offset=frameswritten; 
    416                  
    417                freebob_ringbuffer_get_write_vector(m_event_buffer, vec); 
    418                          
    419                if(vec[0].len==0) { // this indicates a full event buffer 
    420                        debugError("XMT: Event buffer overrun in processor %p\n",this); 
    421                        break; 
    422                
    423                          
    424                /* if we don't take care we will get stuck in an infinite loop 
    425                * because we align to a cluster boundary later 
    426                * the remaining nb of bytes in one write operation can be  
    427                * smaller than one cluster 
    428                * this can happen because the ringbuffer size is always a power of 2 
    429                */ 
    430                if(vec[0].len<cluster_size) { 
    431                          
    432                        // encode to the temporary buffer 
    433                        xrun = transmitBlock(m_cluster_buffer, 1, offset); 
    434                          
    435                        if(xrun<0) { 
    436                                // xrun detected 
    437                                debugError("XMT: Frame buffer underrun in processor %p\n",this); 
    438                                break; 
    439                        
    440                                  
    441                        // use the ringbuffer function to write one cluster  
    442                        // the write function handles the wrap around. 
    443                        freebob_ringbuffer_write(m_event_buffer, 
    444                                                 m_cluster_buffer, 
    445                                                 cluster_size); 
    446                                  
    447                        // we advanced one cluster_size 
    448                        bytes2write-=cluster_size; 
    449                                  
    450                } else { //  
    451                          
    452                        if(bytes2write>vec[0].len) { 
    453                                // align to a cluster boundary 
    454                                byteswritten=vec[0].len-(vec[0].len%cluster_size); 
    455                        } else { 
    456                                byteswritten=bytes2write; 
    457                        
    458                                  
    459                        xrun = transmitBlock(vec[0].buf, 
    460                                             byteswritten/cluster_size, 
    461                                             offset); 
    462                          
    463                        if(xrun<0) { 
    464                                        // xrun detected 
    465                                debugError("XMT: Frame buffer underrun in processor %p\n",this); 
    466                                break; 
    467                        
    468  
    469                        freebob_ringbuffer_write_advance(m_event_buffer, byteswritten); 
    470                        bytes2write -= byteswritten; 
    471                
    472  
    473                // the bytes2write should always be cluster aligned 
    474                assert(bytes2write%cluster_size==0); 
    475  
    476        
    477  
    478        return true; 
     488    int xrun; 
     489    unsigned int offset=0; 
     490     
     491    freebob_ringbuffer_data_t vec[2]; 
     492    // we received one period of frames 
     493    // this is period_size*dimension of events 
     494    int events2write=m_period*m_dimension; 
     495    int bytes2write=events2write*sizeof(quadlet_t); 
     496 
     497    /* write events2write bytes to the ringbuffer  
     498    *  first see if it can be done in one read. 
     499    *  if so, ok.  
     500    *  otherwise write up to a multiple of clusters directly to the buffer 
     501    *  then do the buffer wrap around using ringbuffer_write 
     502    *  then write the remaining data directly to the buffer in a third pass  
     503    *  Make sure that we cannot end up on a non-cluster aligned position! 
     504    */ 
     505    int cluster_size=m_dimension*sizeof(quadlet_t); 
     506 
     507    while(bytes2write>0) { 
     508        int byteswritten=0; 
     509         
     510        unsigned int frameswritten=(m_period*cluster_size-bytes2write)/cluster_size; 
     511        offset=frameswritten; 
     512         
     513        freebob_ringbuffer_get_write_vector(m_event_buffer, vec); 
     514             
     515        if(vec[0].len==0) { // this indicates a full event buffer 
     516            debugError("XMT: Event buffer overrun in processor %p\n",this); 
     517            break; 
     518       
     519             
     520        /* if we don't take care we will get stuck in an infinite loop 
     521        * because we align to a cluster boundary later 
     522        * the remaining nb of bytes in one write operation can be  
     523        * smaller than one cluster 
     524        * this can happen because the ringbuffer size is always a power of 2 
     525        */ 
     526        if(vec[0].len<cluster_size) { 
     527             
     528            // encode to the temporary buffer 
     529            xrun = transmitBlock(m_cluster_buffer, 1, offset); 
     530             
     531            if(xrun<0) { 
     532                // xrun detected 
     533                debugError("XMT: Frame buffer underrun in processor %p\n",this); 
     534                break; 
     535           
     536                 
     537            // use the ringbuffer function to write one cluster  
     538            // the write function handles the wrap around. 
     539            freebob_ringbuffer_write(m_event_buffer, 
     540                        m_cluster_buffer, 
     541                        cluster_size); 
     542                 
     543            // we advanced one cluster_size 
     544            bytes2write-=cluster_size; 
     545                 
     546        } else { //  
     547             
     548            if(bytes2write>vec[0].len) { 
     549                // align to a cluster boundary 
     550                byteswritten=vec[0].len-(vec[0].len%cluster_size); 
     551            } else { 
     552                byteswritten=bytes2write; 
     553           
     554                 
     555            xrun = transmitBlock(vec[0].buf, 
     556                         byteswritten/cluster_size, 
     557                         offset); 
     558             
     559            if(xrun<0) { 
     560                    // xrun detected 
     561                debugError("XMT: Frame buffer underrun in processor %p\n",this); 
     562                break; 
     563           
     564 
     565            freebob_ringbuffer_write_advance(m_event_buffer, byteswritten); 
     566            bytes2write -= byteswritten; 
     567       
     568 
     569        // the bytes2write should always be cluster aligned 
     570        assert(bytes2write%cluster_size==0); 
     571 
     572   
     573 
     574    return true; 
    479575} 
    480576/*  
     
    483579 
    484580int AmdtpTransmitStreamProcessor::transmitBlock(char *data,  
    485                                           unsigned int nevents, unsigned int offset) 
     581                       unsigned int nevents, unsigned int offset) 
    486582{ 
    487        int problem=0; 
    488  
    489        for ( PortVectorIterator it = m_PeriodPorts.begin(); 
     583    int problem=0; 
     584 
     585    for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    490586          it != m_PeriodPorts.end(); 
    491587          ++it ) 
     
    494590        if((*it)->isDisabled()) {continue;}; 
    495591         
    496                //FIXME: make this into a static_cast when not DEBUG? 
    497  
    498                AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    499                assert(pinfo); // this should not fail!! 
    500  
    501                switch(pinfo->getFormat()) { 
    502                case AmdtpPortInfo::E_MBLA: 
    503                        if(encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    504                                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
    505                                problem=1; 
    506                        
    507                        break; 
    508                case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    509                        break; 
    510                default: // ignore 
    511                        break; 
    512                
    513     } 
    514        return problem; 
     592        //FIXME: make this into a static_cast when not DEBUG? 
     593 
     594        AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
     595        assert(pinfo); // this should not fail!! 
     596 
     597        switch(pinfo->getFormat()) { 
     598        case AmdtpPortInfo::E_MBLA: 
     599            if(encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     600                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
     601                problem=1; 
     602           
     603            break; 
     604        case AmdtpPortInfo::E_SPDIF: // still unimplemented 
     605            break; 
     606        default: // ignore 
     607            break; 
     608       
     609    } 
     610    return problem; 
    515611 
    516612} 
    517613 
    518614int AmdtpTransmitStreamProcessor::transmitSilenceBlock(char *data,  
    519                                           unsigned int nevents, unsigned int offset) 
     615                       unsigned int nevents, unsigned int offset) 
    520616{ 
    521        int problem=0; 
    522  
    523        for ( PortVectorIterator it = m_PeriodPorts.begin(); 
     617    int problem=0; 
     618 
     619    for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    524620          it != m_PeriodPorts.end(); 
    525621          ++it ) 
    526622    { 
    527623 
    528                //FIXME: make this into a static_cast when not DEBUG? 
    529  
    530                AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    531                assert(pinfo); // this should not fail!! 
    532  
    533                switch(pinfo->getFormat()) { 
    534                case AmdtpPortInfo::E_MBLA: 
    535                        if(encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    536                                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
    537                                problem=1; 
    538                        
    539                        break; 
    540                case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    541                        break; 
    542                default: // ignore 
    543                        break; 
    544                
    545     } 
    546        return problem; 
     624        //FIXME: make this into a static_cast when not DEBUG? 
     625 
     626        AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
     627        assert(pinfo); // this should not fail!! 
     628 
     629        switch(pinfo->getFormat()) { 
     630        case AmdtpPortInfo::E_MBLA: 
     631            if(encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     632                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
     633                problem=1; 
     634           
     635            break; 
     636        case AmdtpPortInfo::E_SPDIF: // still unimplemented 
     637            break; 
     638        default: // ignore 
     639            break; 
     640       
     641    } 
     642    return problem; 
    547643 
    548644} 
     
    558654bool AmdtpTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc) 
    559655{ 
    560        bool ok=true; 
    561        char byte; 
    562          
    563        quadlet_t *target_event=NULL; 
    564        int j; 
    565          
    566        for ( PortVectorIterator it = m_PacketPorts.begin(); 
     656    bool ok=true; 
     657    char byte; 
     658     
     659    quadlet_t *target_event=NULL; 
     660    int j; 
     661     
     662    for ( PortVectorIterator it = m_PacketPorts.begin(); 
    567663          it != m_PacketPorts.end(); 
    568664          ++it ) 
    569        
     665   
    570666 
    571667#ifdef DEBUG 
    572                AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    573                assert(pinfo); // this should not fail!! 
    574  
    575                // the only packet type of events for AMDTP is MIDI in mbla 
    576                assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi); 
     668        AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
     669        assert(pinfo); // this should not fail!! 
     670 
     671        // the only packet type of events for AMDTP is MIDI in mbla 
     672        assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi); 
    577673#endif 
    578                  
    579                AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it); 
    580                  
    581                // we encode this directly (no function call) due to the high frequency 
    582                /* idea: 
    583                spec says: current_midi_port=(dbc+j)%8; 
    584                => if we start at (dbc+stream->location-1)%8 [due to location_min=1],  
    585                we'll start at the right event for the midi port. 
    586                => if we increment j with 8, we stay at the right event. 
    587                */ 
    588                // FIXME: as we know in advance how big a packet is (syt_interval) we can  
    589                //        predict how much loops will be present here 
    590                // first prefill the buffer with NO_DATA's on all time muxed channels 
    591                  
    592                for(j = (dbc & 0x07)+mp->getLocation()-1; j < nevents; j += 8) { 
    593                  
    594                        target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); 
    595                          
    596                        if(mp->canRead()) { // we can send a byte 
    597                                mp->readEvent(&byte); 
    598                                *target_event=htonl( 
    599                                        IEC61883_AM824_SET_LABEL((byte)<<16, 
    600                                                                 IEC61883_AM824_LABEL_MIDI_1X)); 
    601                        } else {  
    602                                // can't send a byte, either because there is no byte, 
    603                                // or because this would exceed the maximum rate 
    604                                *target_event=htonl( 
    605                                        IEC61883_AM824_SET_LABEL(0,IEC61883_AM824_LABEL_MIDI_NO_DATA)); 
    606                        
    607                
    608  
    609        
    610         
    611        return ok; 
     674         
     675        AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it); 
     676         
     677        // we encode this directly (no function call) due to the high frequency 
     678        /* idea: 
     679        spec says: current_midi_port=(dbc+j)%8; 
     680        => if we start at (dbc+stream->location-1)%8 [due to location_min=1],  
     681        we'll start at the right event for the midi port. 
     682        => if we increment j with 8, we stay at the right event. 
     683        */ 
     684        // FIXME: as we know in advance how big a packet is (syt_interval) we can  
     685        //        predict how much loops will be present here 
     686        // first prefill the buffer with NO_DATA's on all time muxed channels 
     687         
     688        for(j = (dbc & 0x07)+mp->getLocation()-1; j < nevents; j += 8) { 
     689         
     690            target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); 
     691             
     692            if(mp->canRead()) { // we can send a byte 
     693                mp->readEvent(&byte); 
     694                *target_event=htonl( 
     695                    IEC61883_AM824_SET_LABEL((byte)<<16, 
     696                                             IEC61883_AM824_LABEL_MIDI_1X)); 
     697            } else {  
     698                // can't send a byte, either because there is no byte, 
     699                // or because this would exceed the maximum rate 
     700                *target_event=htonl( 
     701                    IEC61883_AM824_SET_LABEL(0,IEC61883_AM824_LABEL_MIDI_NO_DATA)); 
     702           
     703       
     704 
     705   
     706         
     707    return ok; 
    612708} 
    613709 
    614710 
    615711int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents(AmdtpAudioPort *p, quadlet_t *data,  
    616                                           unsigned int offset, unsigned int nevents) 
     712                       unsigned int offset, unsigned int nevents) 
    617713{ 
    618        unsigned int j=0; 
    619  
    620        quadlet_t *target_event; 
    621  
    622        target_event=(quadlet_t *)(data + p->getPosition()); 
    623  
    624        switch(p->getDataType()) { 
    625                default: 
    626                case Port::E_Int24: 
    627                        
    628                                quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
    629  
    630                                assert(nevents + offset <= p->getBufferSize()); 
    631  
    632                                buffer+=offset; 
    633  
    634                                for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    635                                        *target_event = htonl((*(buffer) & 0x00FFFFFF) | 0x40000000); 
    636                                        buffer++; 
    637                                        target_event += m_dimension; 
    638                                
    639                        
    640                        break; 
    641                case Port::E_Float: 
    642                        
    643                                const float multiplier = (float)(0x7FFFFF00); 
    644                                float *buffer=(float *)(p->getBufferAddress()); 
    645  
    646                                assert(nevents + offset <= p->getBufferSize()); 
    647  
    648                                buffer+=offset; 
    649  
    650                                for(j = 0; j < nevents; j += 1) { // decode max nsamples                
    651          
    652                                        // don't care for overflow 
    653                                        float v = *buffer * multiplier;  // v: -231 .. 231 
    654                                        unsigned int tmp = ((int)v); 
    655                                        *target_event = htonl((tmp >> 8) | 0x40000000); 
    656                                          
    657                                        buffer++; 
    658                                        target_event += m_dimension; 
    659                                
    660                        
    661                        break; 
    662        
    663  
    664        return 0; 
     714    unsigned int j=0; 
     715 
     716    quadlet_t *target_event; 
     717 
     718    target_event=(quadlet_t *)(data + p->getPosition()); 
     719 
     720    switch(p->getDataType()) { 
     721        default: 
     722        case Port::E_Int24: 
     723           
     724                quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
     725 
     726                assert(nevents + offset <= p->getBufferSize()); 
     727 
     728                buffer+=offset; 
     729 
     730                for(j = 0; j < nevents; j += 1) { // decode max nsamples 
     731                    *target_event = htonl((*(buffer) & 0x00FFFFFF) | 0x40000000); 
     732                    buffer++; 
     733                    target_event += m_dimension; 
     734               
     735           
     736            break; 
     737        case Port::E_Float: 
     738           
     739                const float multiplier = (float)(0x7FFFFF00); 
     740                float *buffer=(float *)(p->getBufferAddress()); 
     741 
     742                assert(nevents + offset <= p->getBufferSize()); 
     743 
     744                buffer+=offset; 
     745 
     746                for(j = 0; j < nevents; j += 1) { // decode max nsamples               
     747     
     748                    // don't care for overflow 
     749                    float v = *buffer * multiplier;  // v: -231 .. 231 
     750                    unsigned int tmp = ((int)v); 
     751                    *target_event = htonl((tmp >> 8) | 0x40000000); 
     752                     
     753                    buffer++; 
     754                    target_event += m_dimension; 
     755               
     756           
     757            break; 
     758   
     759 
     760    return 0; 
    665761} 
    666762int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents(AmdtpAudioPort *p, quadlet_t *data,  
    667                                           unsigned int offset, unsigned int nevents) 
     763                       unsigned int offset, unsigned int nevents) 
    668764{ 
    669        unsigned int j=0; 
    670  
    671        quadlet_t *target_event; 
    672  
    673        target_event=(quadlet_t *)(data + p->getPosition()); 
    674  
    675        switch(p->getDataType()) { 
    676                default: 
    677                case Port::E_Int24: 
    678                case Port::E_Float: 
    679                        
    680                                for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    681                                        *target_event = htonl(0x40000000); 
    682                                        target_event += m_dimension; 
    683                                
    684                        
    685                        break; 
    686        
    687  
    688        return 0; 
     765    unsigned int j=0; 
     766 
     767    quadlet_t *target_event; 
     768 
     769    target_event=(quadlet_t *)(data + p->getPosition()); 
     770 
     771    switch(p->getDataType()) { 
     772        default: 
     773        case Port::E_Int24: 
     774        case Port::E_Float: 
     775           
     776                for(j = 0; j < nevents; j += 1) { // decode max nsamples 
     777                    *target_event = htonl(0x40000000); 
     778                    target_event += m_dimension; 
     779               
     780           
     781            break; 
     782   
     783 
     784    return 0; 
    689785} 
    690786 
     
    692788 
    693789AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int port, int framerate, int dimension) 
    694        : ReceiveStreamProcessor(port, framerate), m_dimension(dimension) { 
     790    : ReceiveStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0) { 
    695791 
    696792 
     
    698794 
    699795AmdtpReceiveStreamProcessor::~AmdtpReceiveStreamProcessor() { 
    700        freebob_ringbuffer_free(m_event_buffer); 
    701        free(m_cluster_buffer); 
     796    freebob_ringbuffer_free(m_event_buffer); 
     797    free(m_cluster_buffer); 
    702798 
    703799} 
    704800 
    705801bool AmdtpReceiveStreamProcessor::init() { 
    706         // call the parent init 
    707         // this has to be done before allocating the buffers,  
    708         // because this sets the buffersizes from the processormanager 
    709         if(!ReceiveStreamProcessor::init()) { 
    710                 debugFatal("Could not do base class init (%d)\n",this); 
    711                 return false; 
    712         } 
    713  
    714         return true; 
    715 
    716  
    717 int AmdtpReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,  
    718                       unsigned char channel, unsigned char tag, unsigned char sy,  
    719                           unsigned int cycle, unsigned int dropped) { 
    720      
    721         enum raw1394_iso_disposition retval=RAW1394_ISO_OK; 
    722          
    723         struct iec61883_packet *packet = (struct iec61883_packet *) data; 
    724         assert(packet); 
    725          
    726         // how are we going to get this right??? 
    727         m_running=true; 
    728          
    729         if((packet->fmt == 0x10) && (packet->fdf != 0xFF) && (packet->dbs>0) && (length>=2*sizeof(quadlet_t))) { 
    730                 unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs; 
    731                  
    732                 // signal that we're running 
    733 //              if(nevents) m_running=true; 
    734                  
    735                 // don't process the stream when it is not enabled. 
    736                 if(m_disabled) { 
    737                         return (int)RAW1394_ISO_OK; 
    738                 } 
    739                  
    740                 unsigned int write_size=nevents*sizeof(quadlet_t)*m_dimension; 
    741                 // add the data payload to the ringbuffer 
    742                  
    743                 if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size)  
    744                 { 
    745                     debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",  
    746                              cycle, m_framecounter, m_handler->getPacketCount()); 
    747                         m_xruns++; 
    748  
    749                         retval=RAW1394_ISO_DEFER; 
    750                 } else { 
    751                         retval=RAW1394_ISO_OK; 
    752                         // process all ports that should be handled on a per-packet base 
    753                         // this is MIDI for AMDTP (due to the need of DBC) 
    754                         if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) { 
    755                                 debugWarning("Problem decoding Packet Ports\n"); 
    756                     retval=RAW1394_ISO_DEFER; 
    757                         } 
    758                 } 
    759  
    760                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,  
    761                         "RCV: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",  
    762                         channel, packet->fdf, 
    763                         packet->syt, 
    764                         packet->dbs, 
    765                         packet->dbc, 
    766                         packet->fmt,  
    767                         length, 
    768                         ((length / sizeof (quadlet_t)) - 2)/packet->dbs); 
    769                  
    770                 // update the frame counter 
    771                 m_framecounter+=nevents; 
    772                 if(m_framecounter>m_period) { 
    773                retval=RAW1394_ISO_DEFER; 
    774                 } 
    775                  
    776         } else { 
    777                 // discard packet 
    778                 // can be important for sync though 
    779         } 
    780          
     802    // call the parent init 
     803    // this has to be done before allocating the buffers,  
     804    // because this sets the buffersizes from the processormanager 
     805    if(!ReceiveStreamProcessor::init()) { 
     806        debugFatal("Could not do base class init (%d)\n",this); 
     807        return false; 
     808    } 
     809 
     810    return true; 
     811
     812 
     813enum raw1394_iso_disposition  
     814AmdtpReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,  
     815                  unsigned char channel, unsigned char tag, unsigned char sy,  
     816                  unsigned int cycle, unsigned int dropped) { 
     817     
     818    enum raw1394_iso_disposition retval=RAW1394_ISO_OK; 
     819     
     820    struct iec61883_packet *packet = (struct iec61883_packet *) data; 
     821    assert(packet); 
     822     
     823    // how are we going to get this right??? 
     824//     m_running=true; 
     825     
     826    if((packet->fmt == 0x10) && (packet->fdf != 0xFF) && (packet->dbs>0) && (length>=2*sizeof(quadlet_t))) { 
     827        unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs; 
     828         
     829        // signal that we're running 
     830                if(nevents) m_running=true; 
     831         
     832        // don't process the stream when it is not enabled. 
     833        if(m_disabled) { 
     834            return RAW1394_ISO_OK; 
     835        } 
     836        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "put packet...\n"); 
     837         
     838        unsigned int write_size=nevents*sizeof(quadlet_t)*m_dimension; 
     839        // add the data payload to the ringbuffer 
     840         
     841        if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size)  
     842        { 
     843            debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",  
     844                 cycle, m_framecounter, m_handler->getPacketCount()); 
     845            m_xruns++; 
     846 
     847            retval=RAW1394_ISO_DEFER; 
     848        } else { 
     849            retval=RAW1394_ISO_OK; 
     850            // process all ports that should be handled on a per-packet base 
     851            // this is MIDI for AMDTP (due to the need of DBC) 
     852            if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) { 
     853                debugWarning("Problem decoding Packet Ports\n"); 
     854                retval=RAW1394_ISO_DEFER; 
     855            } 
     856             
     857            // do the time stamp processing 
     858            // put the last time stamp a variable 
     859            // this will allow us to determine the  
     860            // actual presentation time later 
     861            if (packet->syt != 0xFFFF) { 
     862                  
     863                m_last_timestamp=ntohs(packet->syt); 
     864                 // reconstruct the top part of the timestamp using the current cycle number 
     865//                  m_last_timestamp |= ((cycle << 12) & 0x01FF0000); 
     866                unsigned int syt_cycles=CYCLE_COUNTER_GET_CYCLES(m_last_timestamp); 
     867                int new_cycles=cycle+(syt_cycles-(cycle & 0xF)); 
     868//                 m_last_timestamp &= 0xFFF; // keep only the offset 
     869//                 m_last_timestamp |= ((new_cycles << 12) & 0x01FFF000); // add the right cycle info 
     870                  
     871                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"R-SYT for cycle (%2d %2d)=>%2d: %5uT (%04uC + %04uT) %04X %04X %d\n", 
     872                 cycle,cycle & 0xF,new_cycles, 
     873                 CYCLE_COUNTER_TO_TICKS(m_last_timestamp), 
     874                 CYCLE_COUNTER_GET_CYCLES(m_last_timestamp), 
     875                 CYCLE_COUNTER_GET_TICKS(m_last_timestamp), 
     876                 ntohs(packet->syt),m_last_timestamp&0xFFFF, dropped 
     877                 ); 
     878            } 
     879        } 
     880 
     881        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,  
     882            "RCV: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",  
     883            channel, packet->fdf, 
     884            packet->syt, 
     885            packet->dbs, 
     886            packet->dbc, 
     887            packet->fmt,  
     888            length, 
     889            ((length / sizeof (quadlet_t)) - 2)/packet->dbs); 
     890         
     891        // update the frame counter 
     892        m_framecounter+=nevents; 
     893        if(m_framecounter>m_period) { 
     894           retval=RAW1394_ISO_DEFER; 
     895           debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"defer!\n"); 
     896        } 
     897         
     898    } else { 
     899        // discard packet 
     900        // can be important for sync though 
     901    } 
     902     
    781903    m_PacketStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    782  
    783         return (int)retval; 
     904     
     905    return retval; 
     906
     907 
     908// this uses SYT to determine if one period is ready 
     909bool AmdtpReceiveStreamProcessor::isOnePeriodReady() {  
     910#if 0 // this code is not ready yet 
     911 
     912    // one sample will take a number off cycle counter ticks: 
     913    // The number of ticks per second is 24576000 
     914    // The number of samples per second is Fs 
     915    // therefore the number of ticks per sample is 24576000 / Fs 
     916    // NOTE: this will be rounded!! 
     917    float ticks_per_sample=24576000.0/m_framerate; 
     918 
     919    // we are allowed to add some constant  
     920    // processing delay to the transfer delay 
     921    // being the period size and some fixed delay 
     922    unsigned int processing_delay=ticks_per_sample*(m_period)+RECEIVE_PROCESSING_DELAY; 
     923     
     924     
     925    // the number of events in the buffer is 
     926    // m_framecounter 
     927 
     928    // we have the timestamp of the last event block: 
     929    // m_last_timestamp 
     930     
     931    // the time at which the beginning of the buffer should be 
     932    // presented to the audio side is: 
     933    // m_last_timestamp - (m_framecounter-m_syt_interval)*ticks_per_sample 
     934     
     935    // however we have to make sure that we can transfer at least one period 
     936    // therefore we first check if this is ok 
     937     
     938     if(m_framecounter > (int)m_period) { 
     939        // we make this signed, because this can be < 0 
     940        unsigned int m_last_timestamp_ticks = CYCLE_COUNTER_TO_TICKS(m_last_timestamp); 
     941         
     942        // add the processing delay 
     943        int ideal_presentation_time = m_last_timestamp_ticks + processing_delay; 
     944        unsigned int buffer_content_ticks=(int)((m_framecounter-m_syt_interval)*ticks_per_sample); 
     945         
     946        // if the ideal_presentation_time is smaller than buffer_content_ticks, wraparound has occurred 
     947        // for the cycle part of m_last_timestamp. Therefore add one second worth of ticks 
     948        // to the cycle counter, as this is the wraparound point. 
     949        if (ideal_presentation_time < buffer_content_ticks) ideal_presentation_time += 24576000; 
     950        // we can now safely substract these, it will always be > 0 
     951        ideal_presentation_time -= buffer_content_ticks; 
     952         
     953        // FIXME: if we are sure, make ideal_presentation_time an unsigned int 
     954//         assert(ideal_presentation_time>=0); 
     955         
     956         
     957/*        if(ideal_presentation_time) { 
     958            debugOutput(DEBUG_LEVEL_VERBOSE, "Presentation time < 0 : %d\n", ideal_presentation_time); 
     959        }*/ 
     960         
     961        unsigned int current_time=m_handler->getCycleCounter() & 0x1FFFFFF; 
     962        unsigned int current_time_ticks = CYCLE_COUNTER_TO_TICKS(current_time); 
     963 
     964        // if the last signalled period lies in the future, we know we had wraparound of the clock 
     965        // so add one second 
     966//         if (current_time_ticks < m_previous_signal_ticks) current_time_ticks += 24576000; 
     967        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Periods: %d\n",m_PeriodStat.m_count); 
     968        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Timestamp : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n", 
     969            m_last_timestamp_ticks, 
     970            CYCLE_COUNTER_GET_SECS(m_last_timestamp),  
     971            CYCLE_COUNTER_GET_CYCLES(m_last_timestamp),  
     972            CYCLE_COUNTER_GET_TICKS(m_last_timestamp) 
     973            ); 
     974        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"P-TIME    : %10d ticks (%3u secs + %4u cycles + %04u ticks)\n", 
     975            ideal_presentation_time, 
     976            ideal_presentation_time/24576000,  
     977            (ideal_presentation_time/3072) % 8000, 
     978            ideal_presentation_time%3072 
     979            ); 
     980        debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Now       : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n", 
     981            current_time_ticks,  
     982            CYCLE_COUNTER_GET_SECS(current_time),  
     983            CYCLE_COUNTER_GET_CYCLES(current_time),  
     984            CYCLE_COUNTER_GET_TICKS(current_time) 
     985            ); 
     986         
     987        int tmp=ideal_presentation_time-current_time_ticks; 
     988         
     989        // if current_time_ticks wraps around while ahead of the presentation time, we have  
     990        // a problem. 
     991        // we know however that we have to wait for at max one buffer + some transmit delay 
     992        // therefore we clip this value at 0.5 seconds 
     993        if (tmp > 24576000/2) tmp-=24576000; 
     994         
     995        if(tmp<0) { 
     996            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT passed (%d ticks too late)\n",-tmp); 
     997            if (-tmp>1000000) debugWarning("SYT VERY LATE: %d!\n",-tmp); 
     998            return true; 
     999        } else { 
     1000            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Too early wait %d ticks\n",tmp); 
     1001            return false; 
     1002        } 
     1003    } else return false; 
     1004#endif 
     1005    if(m_framecounter > (int)m_period) { 
     1006     return true; 
     1007    } 
     1008 
    7841009} 
    7851010 
     
    7971022        // reset the event buffer, discard all content 
    7981023        freebob_ringbuffer_reset(m_event_buffer); 
     1024         
     1025        // reset the last timestamp 
     1026        m_last_timestamp=0; 
     1027         
     1028        m_PeriodStat.reset(); 
     1029    m_PacketStat.reset(); 
     1030    m_WakeupStat.reset(); 
     1031 
    7991032         
    8001033        // reset all non-device specific stuff 
     
    8461079        } 
    8471080 
    848         if( !(m_event_buffer=freebob_ringbuffer_create( 
    849                         (m_dimension * m_nb_buffers * m_period) * sizeof(quadlet_t)))) { 
     1081    // allocate the event buffer 
     1082    unsigned int ringbuffer_size_frames=m_nb_buffers * m_period; 
     1083     
     1084    // add the processing delay 
     1085    debugOutput(DEBUG_LEVEL_VERBOSE,"Adding %u frames of SYT slack buffering...\n",(m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND); 
     1086    ringbuffer_size_frames+=(m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND; 
     1087     
     1088    if( !(m_event_buffer=freebob_ringbuffer_create( 
     1089            (m_dimension * ringbuffer_size_frames) * sizeof(quadlet_t)))) { 
    8501090                debugFatal("Could not allocate memory event ringbuffer"); 
    8511091//              return -ENOMEM; 
  • branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.h

    r227 r244  
    7777        virtual ~AmdtpTransmitStreamProcessor(); 
    7878 
    79         int  
     79        enum raw1394_iso_disposition  
    8080                getPacket(unsigned char *data, unsigned int *length, 
    8181                      unsigned char *tag, unsigned char *sy, 
     
    8686        bool prepare(); 
    8787        bool transfer(); 
    88         bool transferSilence(); 
    8988        virtual void setVerboseLevel(int l); 
     89         
     90        bool isOnePeriodReady(); 
    9091 
    91 // NOTE: shouldn't this be (4*m_period)/(3*m_syt_interval), because every 3 packets, one empty is sent 
    92         unsigned int getPacketsPerPeriod() {return m_period/m_syt_interval;}; 
     92    // We have 1 period of samples = m_period 
     93    // this period takes m_period/m_framerate seconds of time 
     94    // during this time, 8000 packets are sent 
     95//      unsigned int getPacketsPerPeriod() {return (m_period*8000)/m_framerate;}; 
     96     
     97    // however, if we only count the number of used packets 
     98    // it is m_period / m_syt_interval 
     99        unsigned int getPacketsPerPeriod() {return (m_period)/m_syt_interval;}; 
     100         
    93101        unsigned int getMaxPacketSize() {return 4 * (2 + m_syt_interval * m_dimension);};  
    94102 
     
    103111 
    104112        int m_fdf; 
     113         
     114    bool prefill(); 
     115     
     116        bool transferSilence(unsigned int size); 
    105117 
    106118        int transmitBlock(char *data, unsigned int nevents,  
     
    136148        virtual ~AmdtpReceiveStreamProcessor(); 
    137149 
    138         int putPacket(unsigned char *data, unsigned int length,  
     150        enum raw1394_iso_disposition putPacket(unsigned char *data, unsigned int length,  
    139151                      unsigned char channel, unsigned char tag, unsigned char sy,  
    140152                          unsigned int cycle, unsigned int dropped); 
     
    148160        virtual void setVerboseLevel(int l); 
    149161         
    150 // NOTE: shouldn't this be (4*m_period)/(3*m_syt_interval), because every 3 packets, one empty is sent 
    151         unsigned int getPacketsPerPeriod() {return m_period/m_syt_interval;}; 
     162        bool isOnePeriodReady(); 
     163         
     164    // We have 1 period of samples = m_period 
     165    // this period takes m_period/m_framerate seconds of time 
     166    // during this time, 8000 packets are sent 
     167//      unsigned int getPacketsPerPeriod() {return (m_period*8000)/m_framerate;}; 
     168     
     169    // however, if we only count the number of used packets 
     170    // it is m_period / m_syt_interval 
     171        unsigned int getPacketsPerPeriod() {return (m_period)/m_syt_interval;}; 
     172         
    152173        unsigned int getMaxPacketSize() {return 4 * (2 + m_syt_interval * m_dimension);};  
    153174 
     
    163184        int m_dimension; 
    164185        unsigned int m_syt_interval; 
     186     
     187    unsigned int m_last_timestamp; 
     188     
    165189    DECLARE_DEBUG_MODULE; 
    166190 
  • branches/libfreebob-2.0/src/libstreaming/freebob_streaming.cpp

    r242 r244  
    7373 
    7474        struct _freebob_device *dev = new struct _freebob_device; 
     75 
     76    debugFatal("%s built %s %s\n", freebob_get_version(), __DATE__, __TIME__); 
    7577 
    7678        if(!dev) { 
  • branches/libfreebob-2.0/src/libstreaming/IsoHandler.cpp

    r225 r244  
    7979 
    8080/* Base class implementation */ 
     81 
     82IsoHandler::~IsoHandler() { 
     83    stop(); 
     84    if(m_handle) raw1394_destroy_handle(m_handle); 
     85    if(m_handle_util) raw1394_destroy_handle(m_handle_util); 
     86     
     87} 
     88 
    8189bool 
    8290IsoHandler::init() 
     
    94102                return false; 
    95103        } 
    96          
    97104        raw1394_set_userdata(m_handle, static_cast<void *>(this)); 
     105         
     106        // a second handle for utility stuff 
     107        m_handle_util = raw1394_new_handle_on_port( m_port ); 
     108        if ( !m_handle_util ) { 
     109                if ( !errno ) { 
     110                        cerr << "libraw1394 not compatible" << endl; 
     111                } else { 
     112                        perror( "IsoHandler::Initialize: Could not get 1394 handle" ); 
     113                        cerr << "Is ieee1394 and raw1394 driver loaded?" << endl; 
     114                } 
     115                return false; 
     116        } 
     117         
     118        raw1394_set_userdata(m_handle_util, static_cast<void *>(this)); 
    98119         
    99120        if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) { 
     
    112133        raw1394_iso_stop(m_handle);  
    113134        return true; 
    114 }; 
     135
     136 
     137/** 
     138 * Returns the current value of the cycle counter 
     139 * 
     140 * @return the current value of the cycle counter 
     141 */ 
     142#define CSR_CYCLE_TIME            0x200 
     143#define CSR_REGISTER_BASE  0xfffff0000000ULL 
     144 
     145unsigned int IsoHandler::getCycleCounter() { 
     146    quadlet_t buf=0; 
     147     
     148    // normally we should be able to use the same handle 
     149    // because it is not iterated on by any other stuff 
     150    // but I'm not sure 
     151    raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),  
     152        CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf); 
     153         
     154    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Current timestamp: %08X = %u\n",buf, ntohl(buf)); 
     155     
     156    return ntohl(buf) & 0xFFFFFFFF; 
     157
    115158 
    116159void IsoHandler::dumpInfo() 
     
    212255 
    213256        if(m_Client) { 
    214                 if(m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped)) { 
    215 //                      return RAW1394_ISO_AGAIN; 
    216                 } 
     257                return m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped); 
    217258        } 
    218259         
     
    317358 
    318359        if(m_Client) { 
    319         if(m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size)) { 
    320 //                      return RAW1394_ISO_AGAIN; 
    321                 } 
    322         } 
    323  
     360        return m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size); 
     361        } 
     362         
    324363        return RAW1394_ISO_OK; 
    325364} 
  • branches/libfreebob-2.0/src/libstreaming/IsoHandler.h

    r225 r244  
    6161         
    6262                IsoHandler(int port)  
    63                    : m_handle(0), m_port(port),  
     63                   : m_handle(0), m_handle_util(0), m_port(port),  
    6464                   m_buf_packets(400), m_max_packet_size(1024), m_irq_interval(-1), 
    6565                   m_packetcount(0), m_dropped(0), m_Client(0) 
     
    7272                {} 
    7373 
    74                 virtual ~IsoHandler() 
    75                 {} 
     74                virtual ~IsoHandler(); 
    7675 
    7776                virtual bool init(); 
     
    111110 
    112111                virtual bool prepare() = 0; 
    113  
     112                 
     113                unsigned int getCycleCounter(); 
     114     
    114115        protected: 
    115116            raw1394handle_t m_handle; 
    116                 int             m_port; 
     117        raw1394handle_t m_handle_util; 
     118                int             m_port; 
    117119                unsigned int    m_buf_packets; 
    118120                unsigned int    m_max_packet_size; 
  • branches/libfreebob-2.0/src/libstreaming/IsoHandlerManager.cpp

    r230 r244  
    178178} 
    179179 
     180void IsoHandlerManager::disablePolling(IsoStream *stream) { 
     181    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Disable polling on stream %p\n",stream); 
     182        int i=0; 
     183        for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 
     184          it != m_IsoHandlers.end(); 
     185          ++it ) 
     186        { 
     187           if ((*it)->isStreamRegistered(stream)) { 
     188               m_poll_fds[i].events = 0; 
     189               m_poll_fds[i].revents = 0; 
     190            debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "polling disabled\n"); 
     191           } 
     192           i++; 
     193        } 
     194 
     195} 
     196 
     197void IsoHandlerManager::enablePolling(IsoStream *stream) { 
     198    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Enable polling on stream %p\n",stream); 
     199        int i=0; 
     200        for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 
     201          it != m_IsoHandlers.end(); 
     202          ++it ) 
     203        { 
     204           if ((*it)->isStreamRegistered(stream)) { 
     205               m_poll_fds[i].events = POLLIN; 
     206               m_poll_fds[i].revents = 0; 
     207            debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "polling enabled\n"); 
     208           } 
     209           i++; 
     210        } 
     211} 
     212 
     213 
    180214/** 
    181215 * Registers an IsoStream with the IsoHandlerManager. 
     
    214248        // allocate a handler for this stream 
    215249        if (stream->getType()==IsoStream::EST_Receive) { 
     250                // setup the optimal parameters for the raw1394 ISO buffering 
     251                unsigned int packets_per_period=stream->getPacketsPerPeriod(); 
     252                 
     253                // hardware interrupts occur when one DMA block is full, and the size of one DMA 
     254                // block = PAGE_SIZE. Setting the max_packet_size makes sure that the HW irq is  
     255                // occurs at a period boundary (optimal CPU use) 
     256                 
     257                // NOTE: try and use 2 hardware interrupts per period for better latency. 
     258                unsigned int max_packet_size=2 * getpagesize() / packets_per_period; 
     259                if (max_packet_size < stream->getMaxPacketSize()) { 
     260                        max_packet_size=stream->getMaxPacketSize(); 
     261                } 
     262                 
     263                int irq_interval=packets_per_period / 4; 
     264        if(irq_interval <= 0) irq_interval=1; 
     265 
     266                /* the receive buffer size doesn't matter for the latency, 
     267                   but it has a minimal value in order for libraw to operate correctly (300) */ 
     268                int buffers=400; 
     269                 
     270                // create the actual handler 
     271                IsoRecvHandler *h = new IsoRecvHandler(stream->getPort(), buffers, 
     272                                                       max_packet_size, irq_interval); 
     273 
     274                debugOutput( DEBUG_LEVEL_VERBOSE, " registering IsoRecvHandler\n"); 
     275 
     276                if(!h) { 
     277                        debugFatal("Could not create IsoRecvHandler\n"); 
     278                        return false; 
     279                } 
     280 
     281                h->setVerboseLevel(getDebugLevel()); 
     282 
     283                // init the handler 
     284                if(!h->init()) { 
     285                        debugFatal("Could not initialize receive handler\n"); 
     286                        return false; 
     287                } 
     288 
     289                // register the stream with the handler 
     290                if(!h->registerStream(stream)) { 
     291                        debugFatal("Could not register receive stream with handler\n"); 
     292                        return false; 
     293                } 
     294 
     295                // register the handler with the manager 
     296                if(!registerHandler(h)) { 
     297                        debugFatal("Could not register receive handler with manager\n"); 
     298                        return false; 
     299                } 
     300                debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n",stream,h); 
     301        } 
     302         
     303        if (stream->getType()==IsoStream::EST_Transmit) { 
     304         
    216305                // setup the optimal parameters for the raw1394 ISO buffering 
    217306                unsigned int packets_per_period=stream->getPacketsPerPeriod(); 
     
    220309                // occurs at a period boundary (optimal CPU use) 
    221310                // NOTE: try and use 2 interrupts per period for better latency. 
    222                 unsigned int max_packet_size=getpagesize() / packets_per_period * 2; 
    223                 int irq_interval=packets_per_period / 2; 
    224  
     311                unsigned int max_packet_size=2 * getpagesize() / packets_per_period; 
    225312                if (max_packet_size < stream->getMaxPacketSize()) { 
    226313                        max_packet_size=stream->getMaxPacketSize(); 
    227314                } 
    228  
    229                 /* the receive buffer size doesn't matter for the latency, 
    230                    but it has a minimal value in order for libraw to operate correctly (300) */ 
    231                 int buffers=400; 
    232                  
    233                 // create the actual handler 
    234                 IsoRecvHandler *h = new IsoRecvHandler(stream->getPort(), buffers, 
    235                                                        max_packet_size, irq_interval); 
    236  
    237                 debugOutput( DEBUG_LEVEL_VERBOSE, " registering IsoRecvHandler\n"); 
    238  
    239                 if(!h) { 
    240                         debugFatal("Could not create IsoRecvHandler\n"); 
    241                         return false; 
    242                 } 
    243  
    244                 h->setVerboseLevel(getDebugLevel()); 
    245  
    246                 // init the handler 
    247                 if(!h->init()) { 
    248                         debugFatal("Could not initialize receive handler\n"); 
    249                         return false; 
    250                 } 
    251  
    252                 // register the stream with the handler 
    253                 if(!h->registerStream(stream)) { 
    254                         debugFatal("Could not register receive stream with handler\n"); 
    255                         return false; 
    256                 } 
    257  
    258                 // register the handler with the manager 
    259                 if(!registerHandler(h)) { 
    260                         debugFatal("Could not register receive handler with manager\n"); 
    261                         return false; 
    262                 } 
    263                 debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n",stream,h); 
    264         } 
    265          
    266         if (stream->getType()==IsoStream::EST_Transmit) { 
    267          
    268                 // setup the optimal parameters for the raw1394 ISO buffering 
    269                 unsigned int packets_per_period=stream->getPacketsPerPeriod(); 
    270                 // hardware interrupts occur when one DMA block is full, and the size of one DMA 
    271                 // block = PAGE_SIZE. Setting the max_packet_size makes sure that the HW irq is  
    272                 // occurs at a period boundary (optimal CPU use) 
    273                 // NOTE: try and use 2 interrupts per period for better latency. 
    274                 unsigned int max_packet_size=getpagesize() / packets_per_period * 2; 
    275                 int irq_interval=packets_per_period / 2; 
    276  
    277                 if (max_packet_size < stream->getMaxPacketSize()) { 
    278                         max_packet_size=stream->getMaxPacketSize(); 
    279                 } 
    280  
    281                 /* the transmit buffer size should be as low as possible for latency.  
    282                 */ 
     315                 
     316                int irq_interval=packets_per_period / 4; 
     317        if(irq_interval <= 0) irq_interval=1; 
     318 
     319                // the transmit buffer size should be as low as possible for latency.  
     320                // note however that the raw1394 subsystem tries to keep this buffer 
     321                // full, so we have to make sure that we have enough events in our 
     322                // event buffers 
    283323                int buffers=packets_per_period; 
    284                 if (buffers<10) buffers=10;      
     324                 
     325                // NOTE: this is dangerous: what if there is not enough prefill? 
     326//              if (buffers<10) buffers=10;      
    285327                 
    286328                // create the actual handler 
  • branches/libfreebob-2.0/src/libstreaming/IsoHandlerManager.h

    r230 r244  
    8888 
    8989                bool prepare(); ///< prepare the ISO manager and all streams 
     90                 
     91                void disablePolling(IsoStream *); ///< disables polling on a stream 
     92                void enablePolling(IsoStream *); ///< enables polling on a stream 
    9093 
    9194        protected: 
  • branches/libfreebob-2.0/src/libstreaming/IsoStream.cpp

    r230 r244  
    3737IMPL_DEBUG_MODULE( IsoStream, IsoStream, DEBUG_LEVEL_NORMAL ); 
    3838 
    39 int IsoStream::putPacket(unsigned char *data, unsigned int length,  
     39enum raw1394_iso_disposition  
     40IsoStream::putPacket(unsigned char *data, unsigned int length,  
    4041                              unsigned char channel, unsigned char tag, unsigned char sy,  
    4142                                  unsigned int cycle, unsigned int dropped) { 
     
    4546                     length, channel, cycle ); 
    4647 
    47         return 0
     48        return RAW1394_ISO_OK
    4849} 
    4950 
    50 int IsoStream::getPacket(unsigned char *data, unsigned int *length, 
     51enum raw1394_iso_disposition  
     52IsoStream::getPacket(unsigned char *data, unsigned int *length, 
    5153                              unsigned char *tag, unsigned char *sy, 
    5254                              int cycle, unsigned int dropped, unsigned int max_length) { 
     
    6163 
    6264 
    63         return 0
     65        return RAW1394_ISO_OK
    6466} 
    6567 
     
    7577{ 
    7678 
     79        debugOutputShort( DEBUG_LEVEL_NORMAL, "  Address        : %p\n",this); 
    7780        debugOutputShort( DEBUG_LEVEL_NORMAL, "  Stream type    : %s\n", 
    7881             (this->getType()==EST_Receive ? "Receive" : "Transmit")); 
     
    116119    m_handler=0; 
    117120 
    118 }; 
    119121} 
     122 
     123} 
  • branches/libfreebob-2.0/src/libstreaming/IsoStream.h

    r230 r244  
    7878                virtual bool init(); 
    7979 
    80                 virtual int  
     80                virtual enum raw1394_iso_disposition  
    8181                        putPacket(unsigned char *data, unsigned int length,  
    8282                              unsigned char channel, unsigned char tag, unsigned char sy,  
    8383                                  unsigned int cycle, unsigned int dropped); 
    84                 virtual int  
     84                virtual enum raw1394_iso_disposition  
    8585                        getPacket(unsigned char *data, unsigned int *length, 
    8686                              unsigned char *tag, unsigned char *sy, 
     
    9090 
    9191                int getNodeId(); 
    92                          
    93  
     92                 
    9493                virtual bool reset(); 
    9594                virtual bool prepare();  
    96  
     95     
    9796        protected: 
    9897 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessor.cpp

    r233 r244  
    8383} 
    8484 
     85/** 
     86 * Resets the frame counter, the xrun counter, the ports and the iso stream. 
     87 * @return true if reset succeeded 
     88 */ 
    8589bool StreamProcessor::reset() { 
    8690 
     
    151155        } 
    152156        m_disabled=false; 
    153 }; 
    154  
     157
    155158 
    156159/** 
     
    160163void StreamProcessor::decrementFrameCounter() { 
    161164        SUBSTRACT_ATOMIC((SInt32 *)&m_framecounter,m_period); 
    162 }; 
     165} 
    163166 
    164167/** 
     
    168171void StreamProcessor::resetFrameCounter() { 
    169172        ZERO_ATOMIC((SInt32 *)&m_framecounter); 
    170 }; 
     173} 
    171174 
    172175/** 
     
    176179void StreamProcessor::resetXrunCounter() { 
    177180        ZERO_ATOMIC((SInt32 *)&m_xruns); 
    178 }; 
     181} 
    179182 
    180183void StreamProcessor::setVerboseLevel(int l) { 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessor.h

    r233 r244  
    6161        virtual ~StreamProcessor(); 
    6262 
    63         virtual int  
     63        virtual enum raw1394_iso_disposition  
    6464                putPacket(unsigned char *data, unsigned int length,  
    6565                      unsigned char channel, unsigned char tag, unsigned char sy,  
    6666                          unsigned int cycle, unsigned int dropped) = 0; 
    67         virtual int  
     67        virtual enum raw1394_iso_disposition  
    6868                getPacket(unsigned char *data, unsigned int *length, 
    6969                      unsigned char *tag, unsigned char *sy, 
     
    7474        bool xrunOccurred() { return (m_xruns>0);}; 
    7575 
    76         bool isOnePeriodReady() { return (m_framecounter > (int)m_period); }; 
     76    /** 
     77     * This is used for implementing the synchronisation. 
     78     * As long as this function doesn't return true, the current buffer 
     79     * contents are not transfered to the packet decoders. 
     80     * 
     81     * This means that there can be more events in the buffer than 
     82     * one period worth of them, should the synchronisation mechanism  
     83     * require this 
     84     * @return  
     85     */ 
     86        virtual bool isOnePeriodReady()=0; 
     87         
    7788        unsigned int getNbPeriodsReady() { if(m_period) return m_framecounter/m_period; else return 0;}; 
    7889        void decrementFrameCounter(); 
     
    8798        bool isEnabled() {return !m_disabled;}; 
    8899 
    89         virtual bool transfer(); // transfer the buffer contents from/to client 
    90  
    91         virtual bool reset(); // reset the streams & buffers (e.g. after xrun) 
    92  
    93         virtual bool prepare(); // prepare the streams & buffers (e.g. prefill) 
     100        virtual bool transfer(); ///< transfer the buffer contents from/to client 
     101 
     102        virtual bool reset(); ///< reset the streams & buffers (e.g. after xrun) 
     103 
     104        virtual bool prepare(); ///< prepare the streams & buffers (e.g. prefill) 
    94105 
    95106        virtual void dumpInfo(); 
     
    143154        virtual enum EProcessorType getType() {return E_Receive;}; 
    144155         
    145         virtual int  
     156        virtual enum raw1394_iso_disposition  
    146157                getPacket(unsigned char *data, unsigned int *length, 
    147158                      unsigned char *tag, unsigned char *sy, 
    148                       int cycle, unsigned int dropped, unsigned int max_length) {return 0;}; 
     159                      int cycle, unsigned int dropped, unsigned int max_length)  
     160                      {return RAW1394_ISO_STOP;}; 
    149161                       
    150         virtual int putPacket(unsigned char *data, unsigned int length,  
     162        virtual enum raw1394_iso_disposition putPacket(unsigned char *data, unsigned int length,  
    151163                      unsigned char channel, unsigned char tag, unsigned char sy,  
    152164                          unsigned int cycle, unsigned int dropped) = 0; 
     
    173185        virtual enum EProcessorType getType() {return E_Transmit;}; 
    174186 
    175         virtual int  
     187        virtual enum raw1394_iso_disposition  
    176188                putPacket(unsigned char *data, unsigned int length,  
    177189                      unsigned char channel, unsigned char tag, unsigned char sy,  
    178                           unsigned int cycle, unsigned int dropped) {return 0;}; 
     190                          unsigned int cycle, unsigned int dropped) {return RAW1394_ISO_STOP;}; 
    179191                           
    180         virtual int  
     192        virtual enum raw1394_iso_disposition  
    181193                getPacket(unsigned char *data, unsigned int *length, 
    182194                      unsigned char *tag, unsigned char *sy, 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessorManager.cpp

    r233 r244  
    3939 
    4040StreamProcessorManager::StreamProcessorManager(unsigned int period, unsigned int nb_buffers) 
    41         : m_nb_buffers(nb_buffers), m_period(period), m_xruns(0), m_isoManager(0)
     41        : m_nb_buffers(nb_buffers), m_period(period), m_xruns(0), m_isoManager(0), m_nbperiods(0)
    4242 
    4343} 
     
    226226        bool period_ready=true; 
    227227    bool xrun_has_occured=false; 
     228        bool this_period_ready; 
    228229         
    229230        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n"); 
     
    237238                it != m_ReceiveProcessors.end(); 
    238239                ++it ) { 
    239                 period_ready = period_ready && (*it)->isOnePeriodReady(); 
     240                 
     241                this_period_ready = (*it)->isOnePeriodReady(); 
     242                period_ready = period_ready && this_period_ready; 
     243//              if (this_period_ready) { 
     244//                  m_isoManager->disablePolling(*it); 
     245//              } 
     246//               
    240247                xrun_has_occured = xrun_has_occured || (*it)->xrunOccurred(); 
    241248                debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE, "(%d/%d/%d) ", period_ready, xrun_has_occured,(*it)->m_framecounter); 
     
    247254                it != m_TransmitProcessors.end(); 
    248255                ++it ) { 
    249                 period_ready = period_ready && (*it)->isOnePeriodReady(); 
     256                this_period_ready = (*it)->isOnePeriodReady(); 
     257                period_ready = period_ready && this_period_ready; 
     258//              if (this_period_ready) { 
     259//                  m_isoManager->disablePolling(*it); 
     260//              } 
    250261                xrun_has_occured = xrun_has_occured || (*it)->xrunOccurred(); 
    251262                debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE, "(%d/%d/%d) ", period_ready, xrun_has_occured,(*it)->m_framecounter); 
     
    271282                        ++it ) { 
    272283                        (*it)->decrementFrameCounter(); 
     284//                      m_isoManager->enablePolling(*it); 
     285                         
    273286                } 
    274287         
     
    277290                        ++it ) { 
    278291                        (*it)->decrementFrameCounter(); 
    279                 } 
     292//                      m_isoManager->enablePolling(*it); 
     293                } 
     294                 
     295                m_nbperiods++; 
    280296        } 
    281297 
     
    419435                ++it ) {                 
    420436                (*it)->enable(); 
     437                m_isoManager->enablePolling(*it); 
    421438        } 
    422439         
     
    425442                ++it ) { 
    426443                (*it)->enable(); 
     444                m_isoManager->enablePolling(*it); 
    427445        } 
    428446         
     
    623641        debugOutputShort( DEBUG_LEVEL_NORMAL, "----------------------------------------------------\n"); 
    624642        debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping StreamProcessorManager information...\n"); 
     643        debugOutputShort( DEBUG_LEVEL_NORMAL, "Period count: %d\n", m_nbperiods); 
    625644 
    626645        debugOutputShort( DEBUG_LEVEL_NORMAL, " Receive processors...\n"); 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessorManager.h

    r233 r244  
    125125        FreebobPosixThread *m_streamingThread; 
    126126 
     127    unsigned int m_nbperiods; 
     128 
    127129    DECLARE_DEBUG_MODULE; 
    128130 
  • branches/libfreebob-2.0/src/libstreaming/streamstatistics.h

    r243 r244  
    2929    void dumpInfo(); 
    3030    void reset(); 
    31      
    32 private: 
    3331 
    3432    std::string m_name; 
     
    4038    long m_sum; 
    4139     
     40private: 
     41     
    4242}; 
    4343 
  • branches/libfreebob-2.0/tests/Makefile.am

    r192 r244  
    2121        $(LIBAVC1394_CFLAGS) 
    2222 
    23 noinst_PROGRAMS = test-freebob test-extplugcmd freebob-server 
     23noinst_PROGRAMS = # test-freebob test-extplugcmd freebob-server 
    2424noinst_HEADERS =  
    2525 
    26 test_freebob_SOURCES = test-freebob.c 
    27 test_freebob_LDADD   = $(top_builddir)/src/libfreebob.la \ 
    28       $(LIBXML_LIBS) $(LIBAVC1394_LIBS) $(LIBIEC61883_LIBS) 
    29  
    30 test_extplugcmd_SOURCES = test-extplugcmd.cpp 
    31 test_extplugcmd_LDADD = $(top_builddir)/src/libfreebobavc/libfreebobavc.la \ 
    32       $(LIBAVC1394_LIBS) 
    33  
    34 freebob_server_SOURCES = freebob-server.c 
    35 freebob_server_LDADD   = $(top_builddir)/src/libfreebob.la $(LIBXML_LIBS) \ 
    36       $(LIBAVC1394_LIBS) $(LIBIEC61883_LIBS) -lrom1394 
     26# test_freebob_SOURCES = test-freebob.c 
     27# test_freebob_LDADD   = $(top_builddir)/src/libfreebob.la \ 
     28#     $(LIBXML_LIBS) $(LIBAVC1394_LIBS) $(LIBIEC61883_LIBS) 
     29#  
     30# test_extplugcmd_SOURCES = test-extplugcmd.cpp 
     31# test_extplugcmd_LDADD = $(top_builddir)/src/libfreebobavc/libfreebobavc.la \ 
     32#     $(LIBAVC1394_LIBS) 
     33#  
     34# freebob_server_SOURCES = freebob-server.c 
     35# freebob_server_LDADD   = $(top_builddir)/src/libfreebob.la $(LIBXML_LIBS) \ 
     36#     $(LIBAVC1394_LIBS) $(LIBIEC61883_LIBS) -lrom1394 
    3737 
    3838 
    39 #TESTS_ENVIRONMENT 
     39# TESTS_ENVIRONMENT 
    4040TEST = test-freebob