Changeset 402

Show
Ignore:
Timestamp:
02/17/07 15:05:37 (15 years ago)
Author:
pieterpalmers
Message:

adapted the Motu SP to the new stream sync framework

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.cpp

    r401 r402  
    3636#include <assert.h> 
    3737 
    38 #define RECEIVE_PROCESSING_DELAY (TICKS_PER_CYCLE * 2) 
    39  
    4038// in ticks 
    4139#define TRANSMIT_TRANSFER_DELAY 6000U 
     
    127125    int now_cycles = (int)CYCLE_TIMER_GET_CYCLES(ctr); 
    128126     
    129     // the difference between 'now' and the cycle this 
    130     // packet is intended for 
     127    // the difference between the cycle this 
     128    // packet is intended for and 'now' 
    131129    int cycle_diff = substractCycles(cycle, now_cycles); 
    132130     
     
    175173             
    176174            #ifdef DEBUG 
    177             if ((unsigned int)m_data_buffer->getFrameCounter() != m_ringbuffer_size_frames) { 
    178                 debugWarning("m_data_buffer->getFrameCounter() != m_ringbuffer_size_frames\n"); 
     175            if ((unsigned int)m_data_buffer->getFrameCounter() != m_data_buffer->getBufferSize()) { 
     176                debugWarning("m_data_buffer->getFrameCounter() != m_data_buffer->getBufferSize()\n"); 
    179177            } 
    180178            #endif 
     
    323321    } else { // there is no more data in the ringbuffer 
    324322 
    325         // TODO: maybe we have to be a little smarter here 
    326         //       because we have some slack on the device side (TRANSFER_DELAY) 
    327         //       we can allow some skipped packets 
    328323        debugWarning("Transmit buffer underrun (now %d, queue %d, target %d)\n",  
    329324                 now_cycles, cycle, TICKS_TO_CYCLES(ts)); 
     
    471466    m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate); 
    472467     
    473     // allocate the event buffer 
     468       // initialize internal buffer 
    474469    m_ringbuffer_size_frames=m_nb_buffers * m_period; 
    475470 
     
    952947    } 
    953948 
     949    // check if this is a valid packet 
    954950    if((packet->syt != 0xFFFF)  
    955951       && (packet->fdf != 0xFF)  
     
    10621058int AmdtpReceiveStreamProcessor::getMinimalSyncDelay() { 
    10631059    return (int)(m_handler->getWakeupInterval() * m_syt_interval * m_ticks_per_frame); 
    1064 //     return RECEIVE_PROCESSING_DELAY; 
    1065 
    1066  
    1067 void AmdtpReceiveStreamProcessor::dumpInfo() 
    1068 
    1069  
     1060
     1061 
     1062void AmdtpReceiveStreamProcessor::dumpInfo() { 
    10701063    StreamProcessor::dumpInfo(); 
    1071  
    1072 
    1073  
     1064
    10741065 
    10751066void AmdtpReceiveStreamProcessor::setVerboseLevel(int l) { 
    10761067        setDebugLevel(l); 
    1077         ReceiveStreamProcessor::setVerboseLevel(l); 
    1078  
     1068        ReceiveStreamProcessor::setVerboseLevel(l); 
    10791069} 
    10801070 
     
    10901080    // the result is that we get some extra time before period boundaries 
    10911081    // are signaled. 
    1092     // The RECEIVE_PROCESSING_DELAY directly introduces some slack 
    1093     // the other term handles the fact that the linux1394 stack does some 
    1094     // buffering. This buffering causes the packets to be received at max 
     1082    // ISO buffering causes the packets to be received at max 
    10951083    // m_handler->getWakeupInterval() later than the time they were received. 
    10961084    // hence their payload is available this amount of time later. However, the 
     
    11541142    debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n",m_ticks_per_frame); 
    11551143 
    1156     // allocate the event buffer 
     1144       // initialize internal buffer 
    11571145    unsigned int ringbuffer_size_frames=m_nb_buffers * m_period; 
    1158      
    1159     // add the processing delay 
    1160     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding %u frames of SYT slack buffering...\n", 
    1161         (uint)(RECEIVE_PROCESSING_DELAY/m_ticks_per_frame)); 
    1162     ringbuffer_size_frames+=(uint)(RECEIVE_PROCESSING_DELAY/m_ticks_per_frame); 
    11631146     
    11641147    assert(m_data_buffer);     
     
    11731156    m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND); 
    11741157     
    1175     // offset is in reset() 
    1176  
    11771158    m_data_buffer->prepare(); 
    11781159 
     
    12341215                                break; 
    12351216                } 
    1236  
    12371217        } 
    12381218 
  • branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.h

    r401 r402  
    7474 
    7575public: 
    76     // FIXME: debug 
    77     friend class AmdtpReceiveStreamProcessor; 
    78      
    7976    AmdtpTransmitStreamProcessor(int port, int framerate, int dimension); 
    8077 
     
    159156 
    160157public: 
    161     // FIXME: debug 
    162     friend class AmdtpTransmitStreamProcessor; 
    163  
    164158        AmdtpReceiveStreamProcessor(int port, int framerate, int dimension); 
    165159 
  • branches/streaming-rework/src/libstreaming/MotuStreamProcessor.cpp

    r384 r402  
    3838#include <netinet/in.h> 
    3939 
     40#include "cycletimer.h" 
     41 
     42// in ticks 
     43#define TRANSMIT_TRANSFER_DELAY 6000U 
     44// the number of cycles to send a packet in advance of it's timestamp 
     45#define TRANSMIT_ADVANCE_CYCLES 1U 
     46 
    4047namespace FreebobStreaming { 
    4148 
     
    5360                unsigned int event_size) 
    5461        : TransmitStreamProcessor(port, framerate), m_event_size(event_size), 
    55         m_tx_dbc(0), m_cycle_count(-1), m_cycle_ofs(0.0), m_next_cycle(-1),  
    56         m_ticks_per_frame(NULL), m_closedown_count(-1), m_streaming_active(0) { 
     62        m_tx_dbc(0), 
     63        m_closedown_count(-1), m_streaming_active(0) { 
    5764} 
    5865 
    5966MotuTransmitStreamProcessor::~MotuTransmitStreamProcessor() { 
    60         freebob_ringbuffer_free(m_event_buffer); 
    61         free(m_tmp_event_buffer); 
     67 
    6268} 
    6369 
     
    8995// FIXME: the actual delays in the system need to be worked out so 
    9096// we can get this thing synchronised.  For now this seems to work. 
    91 #define CYCLE_DELAY 1 
    92  
    93         enum raw1394_iso_disposition retval = RAW1394_ISO_OK; 
     97    uint64_t ts_head, fc; 
     98 
    9499        quadlet_t *quadlet = (quadlet_t *)data; 
    95100        signed int i; 
    96         signed int unwrapped_cycle = cycle; 
    97  
     101         
     102    m_last_cycle=cycle; 
     103     
     104    // determine if we want to send a packet or not 
     105    // note that we can't use getCycleTimer directly here, 
     106    // because packets are queued in advance. This means that 
     107    // we the packet we are constructing will be sent out  
     108    // on 'cycle', not 'now'. 
     109    unsigned int ctr=m_handler->getCycleTimer(); 
     110    int now_cycles = (int)CYCLE_TIMER_GET_CYCLES(ctr); 
     111     
     112    // the difference between the cycle this 
     113    // packet is intended for and 'now' 
     114    int cycle_diff = substractCycles(cycle, now_cycles); 
     115     
    98116        // Signal that streaming is still active 
    99117        m_streaming_active = 1; 
    100118 
    101         // The MOTU transmit stream is 'always' ready 
    102         m_running = true; 
    103          
    104         // Initialise the cycle timer if this is the first time 
    105         // iso data has been requested. 
    106         if (!m_disabled && m_cycle_count<0) { 
    107                 m_cycle_count = cycle; 
    108                 m_cycle_ofs = 0.0; 
    109         } 
    110  
    111         // Similarly, initialise the "next cycle".  This can be done 
    112         // whenever iso data is seen - it doesn't have to wait until 
    113         // the stream is enabled. 
    114         if (m_next_cycle < 0) 
    115                 m_next_cycle = cycle; 
     119    // as long as the cycle parameter is not in sync with 
     120    // the current time, the stream is considered not 
     121    // to be 'running' 
     122    // NOTE: this works only at startup 
     123    if (!m_running && cycle_diff >= 0 && cycle != -1) { 
     124            debugOutput(DEBUG_LEVEL_VERBOSE, "Xmit StreamProcessor %p started running at cycle %d\n",this, cycle); 
     125            m_running=true; 
     126    } 
     127 
     128    if (!m_disabled && m_is_disabled) { 
     129        // this means that we are trying to enable 
     130        if ((unsigned int)cycle == m_cycle_to_enable_at) { 
     131            m_is_disabled=false; 
     132             
     133            debugOutput(DEBUG_LEVEL_VERBOSE,"Enabling StreamProcessor %p at %u\n", this, cycle); 
     134             
     135            // initialize the buffer head & tail 
     136            m_SyncSource->m_data_buffer->getBufferHeadTimestamp(&ts_head, &fc); // thread safe 
     137             
     138            // the number of cycles the sync source lags (> 0) 
     139            // or leads (< 0) 
     140            int sync_lag_cycles=substractCycles(cycle, m_SyncSource->getLastCycle()); 
     141             
     142            // account for the cycle lag between sync SP and this SP 
     143            // the last update of the sync source's timestamps was sync_lag_cycles 
     144            // cycles before the cycle we are calculating the timestamp for. 
     145            // if we were to use one-frame buffers, you would expect the  
     146            // frame that is sent on cycle CT to have a timestamp T1. 
     147            // ts_head however is for cycle CT-sync_lag_cycles, and lies 
     148            // therefore sync_lag_cycles * TICKS_PER_CYCLE earlier than 
     149            // T1. 
     150            ts_head = addTicks(ts_head, sync_lag_cycles * TICKS_PER_CYCLE); 
     151             
     152            m_data_buffer->setBufferTailTimestamp(ts_head); 
     153             
     154            #ifdef DEBUG 
     155            if ((unsigned int)m_data_buffer->getFrameCounter() != m_data_buffer->getBufferSize()) { 
     156                debugWarning("m_data_buffer->getFrameCounter() != m_data_buffer->getBufferSize()\n"); 
     157            } 
     158            #endif 
     159            debugOutput(DEBUG_LEVEL_VERBOSE,"XMIT TS SET: TS=%10lld, LAG=%03d, FC=%4d\n", 
     160                            ts_head, sync_lag_cycles, m_data_buffer->getFrameCounter()); 
     161        } else { 
     162            debugOutput(DEBUG_LEVEL_VERY_VERBOSE, 
     163                        "will enable StreamProcessor %p at %u, now is %d\n", 
     164                        this, m_cycle_to_enable_at, cycle); 
     165        } 
     166    } else if (m_disabled && !m_is_disabled) { 
     167        // trying to disable 
     168        debugOutput(DEBUG_LEVEL_VERBOSE,"disabling StreamProcessor %p at %u\n",  
     169                    this, cycle); 
     170        m_is_disabled=true; 
     171    } 
    116172 
    117173        // Do housekeeping expected for all packets sent to the MOTU, even 
     
    120176        *tag = 1;      // All MOTU packets have a CIP-like header 
    121177 
    122         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); 
    123  
     178 
     179    // the base timestamp is the one of the next sample in the buffer 
     180    m_data_buffer->getBufferHeadTimestamp(&ts_head, &fc); // thread safe 
     181     
     182    int64_t timestamp = ts_head; 
     183 
     184    // we send a packet some cycles in advance, to avoid the 
     185    // following situation: 
     186    // suppose we are only a few ticks away from  
     187    // the moment to send this packet. therefore we decide 
     188    // not to send the packet, but send it in the next cycle. 
     189    // This means that the next time point will be 3072 ticks 
     190    // later, making that the timestamp will be expired when the  
     191    // packet is sent, unless TRANSFER_DELAY > 3072. 
     192    // this means that we need at least one cycle of extra buffering. 
     193    uint64_t ticks_to_advance = TICKS_PER_CYCLE * TRANSMIT_ADVANCE_CYCLES; 
     194     
     195    // if cycle lies cycle_diff cycles in the future, we should 
     196    // queue this packet cycle_diff * TICKS_PER_CYCLE earlier than 
     197    // we would if it were to be sent immediately. 
     198    ticks_to_advance += cycle_diff * TICKS_PER_CYCLE; 
     199 
     200    // determine the 'now' time in ticks 
     201    uint64_t cycle_timer=CYCLE_TIMER_TO_TICKS(ctr); 
     202     
     203    // time until the packet is to be sent (if > 0: send packet) 
     204    int64_t until_next=substractTicks(timestamp, cycle_timer + ticks_to_advance); 
     205     
    124206        // Size of a single data frame in quadlets 
    125207        unsigned dbs = m_event_size / 4; 
     208         
     209    // don't process the stream when it is not enabled, not running 
     210    // or when the next sample is not due yet. 
     211    if((until_next>0) || m_is_disabled || !m_running) { 
     212        // send dummy packet 
     213         
     214        // construct the packet CIP-like header.  Even if this is a data-less  
     215        // packet the dbs field is still set as if there were data blocks  
     216        // present.  For data-less packets the dbc is the same as the previously 
     217        // transmitted block. 
     218        *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); 
     219        quadlet++; 
     220        *quadlet = htonl(0x8222ffff); 
     221        quadlet++; 
     222        *length = 8; 
     223         
     224        #warning high-pitched sound protection removed! 
     225        // In the disabled state simply zero all data sent to the MOTU.  If 
     226        // a stream of empty packets are sent once iso streaming is enabled 
     227        // the MOTU tends to emit high-pitched audio (approx 10 kHz) for 
     228        // some reason.  This is not completely sufficient, however (zeroed 
     229        // packets must also be sent on iso closedown). 
     230     
     231        // FIXME: Currently we simply send empty packets to the MOTU when 
     232        // the stream is disabled so the "m_disabled == 0" code is never 
     233        // executed.  However, this may change in future so it's left in  
     234        // for the moment for reference. 
     235        // FIXME: Currently we don't read the buffer at all during closedown. 
     236        // We could (and silently junk the contents) if it turned out to be 
     237        // more helpful. 
     238         
     239        return RAW1394_ISO_DEFER; 
     240    } 
    126241 
    127242        // The number of events expected by the MOTU is solely dependent on 
     
    130245        signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32); 
    131246 
    132         // Size of data to read from the event buffer, in bytes. 
    133         unsigned int read_size = n_events * m_event_size; 
    134  
    135         // Detect a missed cycle and attempt to "catch up". 
    136         if (cycle != m_next_cycle) { 
    137                 debugOutput(DEBUG_LEVEL_VERBOSE, "tx cycle miss: %d requested, %d expected\n",cycle,m_next_cycle); 
    138         } 
    139         // Attempt to catch up any missed cycles but only if we're enabled. 
    140         if (!m_disabled && cycle!=m_next_cycle) { 
    141                 float ftmp; 
    142                 signed int ccount = m_next_cycle; 
    143  
    144                 while (ccount!=cycle) { 
    145                         unwrapped_cycle = ccount; 
    146                         if (m_cycle_count-ccount > 7900) 
    147                                 unwrapped_cycle += 8000; 
    148  
    149                         if (unwrapped_cycle < m_cycle_count) { 
    150                                 if (++ccount == 8000) 
    151                                         ccount = 0; 
    152                                 continue; 
    153                         } 
    154                         // Advance buffers and counters as if this cycle had been dealt with 
    155                         m_tx_dbc += n_events; 
    156                         incrementFrameCounter(n_events); 
    157  
    158                         ftmp = m_cycle_ofs+n_events*(*m_ticks_per_frame); 
    159                         m_cycle_count += (unsigned int)ftmp/3072; 
    160                         m_cycle_count %= 8000; 
    161                         m_cycle_ofs = fmod(ftmp, 3072); 
    162  
    163                         if (++ccount == 8000) 
    164                                 ccount = 0; 
    165  
    166                         // Also advance the event buffer to keep things in sync 
    167                         freebob_ringbuffer_read_advance(m_event_buffer,read_size); 
    168                 } 
    169                 m_tx_dbc &= 0xff; 
    170                 debugOutput(DEBUG_LEVEL_VERBOSE, "  resuming with cyclecount=%d, cycleofs=%g (ticksperfame=%g)\n", 
    171                         m_cycle_count, m_cycle_ofs, *m_ticks_per_frame); 
    172  
    173                 m_next_cycle = cycle; 
    174         } 
    175  
    176         if ((m_next_cycle=cycle+1) >= 8000) 
    177                 m_next_cycle -= 8000; 
    178  
    179         // Deal cleanly with potential wrap-around cycle timer conditions 
    180         unwrapped_cycle = cycle; 
    181         if (m_cycle_count-cycle > 7900) 
    182                 unwrapped_cycle += 8000; 
    183  
    184         // Increment the dbc (data block count).  This is only done if the 
    185         // packet will contain events - that is, we are due to send some 
    186         // data.  Otherwise a pad packet is sent which contains the DBC of 
    187         // the previously sent packet.  This regime also means that the very 
    188         // first packet containing data will have a DBC of n_events, which 
    189         // matches what is observed from other systems. 
    190         if (!m_disabled && unwrapped_cycle>=m_cycle_count) { 
    191                 m_tx_dbc += n_events; 
    192                 if (m_tx_dbc > 0xff) 
    193                         m_tx_dbc -= 0x100; 
    194         } 
    195  
    196         // construct the packet CIP-like header.  Even if this is a data-less  
    197         // packet the dbs field is still set as if there were data blocks  
    198         // present.  For data-less packets the dbc is the same as the previously 
    199         // transmitted block. 
    200         *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); 
    201         quadlet++; 
    202         *quadlet = htonl(0x8222ffff); 
    203         quadlet++; 
    204         *length = 8; 
    205  
    206         // If the stream is disabled or the MOTU transmission cycle count is 
    207         // ahead of the ieee1394 cycle timer, we send a data-less packet 
    208         // with only the 8 byte CIP-like header set up previously. 
    209         if (m_disabled || unwrapped_cycle<m_cycle_count) { 
    210                 return RAW1394_ISO_OK; 
    211         } 
    212  
    213         // In the disabled state simply zero all data sent to the MOTU.  If 
    214         // a stream of empty packets are sent once iso streaming is enabled 
    215         // the MOTU tends to emit high-pitched audio (approx 10 kHz) for 
    216         // some reason.  This is not completely sufficient, however (zeroed 
    217         // packets must also be sent on iso closedown). 
    218  
    219         // FIXME: Currently we simply send empty packets to the MOTU when 
    220         // the stream is disabled so the "m_disabled == 0" code is never 
    221         // executed.  However, this may change in future so it's left in  
    222         // for the moment for reference. 
    223         // FIXME: Currently we don't read the buffer at all during closedown. 
    224         // We could (and silently junk the contents) if it turned out to be 
    225         // more helpful. 
    226         if (!m_disabled && m_closedown_count<0) { 
    227                 // We read the packet data from a ringbuffer because of 
    228                 // efficiency; it allows us to construct the packets one 
    229                 // period at once. 
    230                 i = freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size) < 
    231                         read_size; 
    232         } else { 
    233                 memset(data+8, 0, read_size); 
    234                 i = 0; 
    235         } 
    236         if (i == 1) { 
    237                 /* there is no more data in the ringbuffer */ 
    238                 debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",  
    239                         cycle, m_framecounter, m_handler->getPacketCount()); 
    240  
    241                 // signal underrun 
    242                 m_xruns++; 
    243  
    244                 retval=RAW1394_ISO_DEFER; // make raw1394_loop_iterate exit its inner loop 
    245                 n_events = 0; 
    246  
    247         } else { 
    248  
    249                 retval=RAW1394_ISO_OK; 
    250                 *length += read_size; 
    251  
     247    // add the transmit transfer delay to construct the playout time 
     248    uint64_t ts=addTicks(timestamp, TRANSMIT_TRANSFER_DELAY); 
     249     
     250    if (m_data_buffer->readFrames(n_events, (char *)(data + 8))) { 
     251     
     252        // Increment the dbc (data block count).  This is only done if the 
     253        // packet will contain events - that is, we are due to send some 
     254        // data.  Otherwise a pad packet is sent which contains the DBC of 
     255        // the previously sent packet.  This regime also means that the very 
     256        // first packet containing data will have a DBC of n_events, which 
     257        // matches what is observed from other systems. 
     258        m_tx_dbc += n_events; 
     259        if (m_tx_dbc > 0xff) 
     260            m_tx_dbc -= 0x100; 
     261     
     262        // construct the packet CIP-like header.  Even if this is a data-less  
     263        // packet the dbs field is still set as if there were data blocks  
     264        // present.  For data-less packets the dbc is the same as the previously 
     265        // transmitted block. 
     266        *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); 
     267        quadlet++; 
     268        *quadlet = htonl(0x8222ffff); 
     269        quadlet++; 
     270 
     271        *length = n_events*m_event_size + 8; 
     272 
     273        // convert the timestamp to Motu format 
     274        // I assume that it is in ticks, and wraps as the cycle timer 
     275        #warning syt conversion to be done 
     276         
    252277                // FIXME: if we choose to read the buffer even during closedown, 
    253278                // here is where the data is silenced. 
     
    259284                // Set up each frames's SPH.  Note that the (int) typecast 
    260285                // appears to do rounding. 
    261                 // 
    262                 // CYCLE_DELAY accounts for the delay between the cycle 
    263                 // audio is sent in and when the MOTU can actually play  
    264                 // that audio.  The SPH timestamp must account for this 
    265                 // so it doesn't demand to be played before it's possible. 
    266                 // For the duration of the event loop, account for the 
    267                 // CYCLE_DELAY within m_cycle_count to save having to wrap 
    268                 // (m_cycle_count+CYCLE_DELAY) and m_cycle_count separately 
    269                 // within the event loop.  Once the loop is finished we 
    270                 // reset m_cyle_count to once again refer to the send 
    271                 // cycle rather than the audio presentation cycle. 
    272                 // 
    273                 // This seemingly messy treatment saves one modulo operation 
    274                 // per loop iteration.  Since the loop count ranges from 8 
    275                 // (for 1x sample rates) to 32 there are considerable 
    276                 // savings to be made even at 1x rates. 
    277                 if ((m_cycle_count+=CYCLE_DELAY) >= 8000) 
    278                         m_cycle_count -= 8000; 
     286 
    279287                for (i=0; i<n_events; i++, quadlet += dbs) { 
    280                         *quadlet = htonl( (m_cycle_count<<12) + (int)m_cycle_ofs); 
    281 #if TESTTONE 
    282                         // FIXME: remove this hacked in 1 kHz test signal to 
    283                         // analog-1 when testing is complete.  Note that the tone is 
    284                         // *never* added during closedown. 
    285                         if (m_closedown_count<0) { 
    286                                 static signed int a_cx = 0; 
    287                                 signed int val; 
    288                                 val = (int)(0x7fffff*sin(1000.0*2.0*M_PI*(a_cx/24576000.0))); 
    289                                 if ((a_cx+=512) >= 24576000) { 
    290                                         a_cx -= 24576000; 
    291                                 } 
    292                                 *(data+8+i*m_event_size+16) = (val >> 16) & 0xff; 
    293                                 *(data+8+i*m_event_size+17) = (val >> 8) & 0xff; 
    294                                 *(data+8+i*m_event_size+18) = val & 0xff; 
    295                         } 
    296 #endif 
    297                         if ((m_cycle_ofs+=*m_ticks_per_frame) >= 3072) { 
    298                                 m_cycle_ofs -= 3072; 
    299                                 if (++m_cycle_count > 7999) 
    300                                         m_cycle_count -= 8000; 
    301                         } 
     288                        *quadlet = htonl( TICKS_TO_CYCLE_TIMER(ts) ); 
    302289                } 
    303                 // Reset m_cycle_count to the send cycle 
    304                 if ((m_cycle_count-=CYCLE_DELAY) < 0) 
    305                         m_cycle_count += 8000; 
    306290 
    307291                // Process all ports that should be handled on a per-packet base 
     
    318302                        debugWarning("Problem encoding Packet Ports\n"); 
    319303                } 
    320         } 
    321      
    322         // Update the frame counter 
    323         incrementFrameCounter(n_events); 
    324  
    325         // Keep this at the end, because otherwise the raw1394_loop_iterate 
    326         // functions inner loop keeps requesting packets, that are not 
    327         // nescessarily ready 
    328  
    329 // Amdtp has this commented out 
    330         if (m_framecounter > (signed int)m_period) { 
    331                 retval=RAW1394_ISO_DEFER; 
    332         } 
    333          
    334         return retval; 
    335 
    336  
    337 bool MotuTransmitStreamProcessor::isOnePeriodReady() {  
    338         // TODO: this is the way you can implement sync 
    339         //       only when this returns true, one period will be 
    340         //       transferred to the audio api side. 
    341         //       you can delay this moment as long as you 
    342         //       want (provided that there is enough buffer space) 
    343          
    344         // this implementation just waits until there is one period of samples 
    345         // transmitted from the buffer 
    346  
    347 // Amdtp has this commented out and simply return true. 
    348         return (m_framecounter > (signed int)m_period);  
    349 //      return true; 
    350 
    351   
     304 
     305        return RAW1394_ISO_OK; 
     306         
     307    } else if (now_cycles<cycle) { 
     308        // we can still postpone the queueing of the packets 
     309        return RAW1394_ISO_AGAIN; 
     310    } else { // there is no more data in the ringbuffer 
     311 
     312        debugWarning("Transmit buffer underrun (now %d, queue %d, target %d)\n",  
     313                 now_cycles, cycle, TICKS_TO_CYCLES(ts)); 
     314 
     315        // signal underrun 
     316        m_xruns++; 
     317 
     318        // disable the processing, will be re-enabled when 
     319        // the xrun is handled 
     320        m_disabled=true; 
     321        m_is_disabled=true; 
     322 
     323        // compose a no-data packet, we should always 
     324        // send a valid packet 
     325         
     326        // send dummy packet 
     327         
     328        // construct the packet CIP-like header.  Even if this is a data-less  
     329        // packet the dbs field is still set as if there were data blocks  
     330        // present.  For data-less packets the dbc is the same as the previously 
     331        // transmitted block. 
     332        *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); 
     333        quadlet++; 
     334        *quadlet = htonl(0x8222ffff); 
     335        quadlet++; 
     336        *length = 8; 
     337 
     338        return RAW1394_ISO_DEFER; 
     339    } 
     340 
     341    // we shouldn't get here 
     342    return RAW1394_ISO_ERROR; 
     343 
     344
     345 
     346int MotuTransmitStreamProcessor::getMinimalSyncDelay() { 
     347    return 0; 
     348
     349 
    352350bool MotuTransmitStreamProcessor::prefill() { 
    353351        // this is needed because otherwise there is no data to be  
     
    368366        debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n"); 
    369367 
    370         // reset the event buffer, discard all content 
    371         freebob_ringbuffer_reset(m_event_buffer); 
     368    // we have to make sure that the buffer HEAD timestamp 
     369    // lies in the future for every possible buffer fill case. 
     370    int offset=(int)(m_data_buffer->getBufferSize()*m_ticks_per_frame); 
     371     
     372    // we can substract the delay as it introduces 
     373    // unnescessary delay 
     374    offset -= m_SyncSource->getSyncDelay(); 
     375     
     376    m_data_buffer->setTickOffset(offset); 
    372377     
    373378        // reset all non-device specific stuff 
     
    406411        // allocate the event buffer 
    407412        unsigned int ringbuffer_size_frames=m_nb_buffers * m_period; 
    408      
    409         if( !(m_event_buffer=freebob_ringbuffer_create( 
    410           m_event_size * ringbuffer_size_frames))) { 
    411                 debugFatal("Could not allocate memory event ringbuffer"); 
    412                 return false; 
    413         } 
    414  
    415         // Allocate the temporary event buffer.  This is needed for the 
    416         // efficient transfer() routine.  Its size has to be equal to one 
    417         // 'event'. 
    418         if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) { 
    419                 debugFatal("Could not allocate temporary event buffer"); 
    420                 freebob_ringbuffer_free(m_event_buffer); 
    421                 return false; 
    422         } 
     413 
     414    // allocate the internal buffer 
     415    float ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate); 
     416        unsigned int events_per_frame = m_framerate<=48000?8:(m_framerate<=96000?16:32); 
     417 
     418    assert(m_data_buffer);     
     419    m_data_buffer->setBufferSize(ringbuffer_size_frames); 
     420    m_data_buffer->setEventSize(m_event_size/events_per_frame); 
     421    m_data_buffer->setEventsPerFrame(events_per_frame); 
     422     
     423    m_data_buffer->setUpdatePeriod(m_period); 
     424    m_data_buffer->setNominalRate(ticks_per_frame); 
     425     
     426    // FIXME: check if the timestamp wraps at one second 
     427    m_data_buffer->setWrapValue(TICKS_PER_SECOND); 
     428     
     429    m_data_buffer->prepare(); 
    423430 
    424431        // Set the parameters of ports we can: we want the audio ports to be 
     
    483490        } 
    484491 
    485         // We should prefill the event buffer 
    486         if (!prefill()) { 
    487                 debugFatal("Could not prefill buffers\n"); 
    488                 return false;     
    489         } 
    490  
    491492        return true; 
    492493} 
    493494 
     495bool MotuTransmitStreamProcessor::prepareForStop() { 
     496 
     497        // If the stream is disabled or isn't running there's no need to 
     498        // wait since the MOTU *should* still be in a "zero data" state. 
     499        // 
     500        // If the m_streaming_active flag is 0 it indicates that the 
     501        // transmit callback hasn't been called since a closedown was 
     502        // requested when this function was last called.  This effectively 
     503        // signifies that the streaming thread has been exitted due to an 
     504        // xrun in either the receive or transmit handlers.  In this case 
     505        // there's no point in waiting for the closedown count to hit zero 
     506        // because it never will; the zero data will never get to the MOTU.  
     507        // It's best to allow an immediate stop and let the xrun handler 
     508        // proceed as best it can. 
     509        // 
     510        // The ability to detect the lack of streaming also prevents the 
     511        // "wait for stop" in the stream processor manager's stop() method 
     512        // from hitting its timeout which in turn seems to increase the 
     513        // probability of a successful recovery. 
     514        if (m_is_disabled || !isRunning() || !m_streaming_active) 
     515                return true; 
     516 
     517        if (m_closedown_count < 0) { 
     518                // No closedown has been initiated, so start one now.  Set 
     519                // the closedown count to the number of zero packets which 
     520                // will be sent to the MOTU before closing off the iso 
     521                // streams.  FIXME: 128 packets (each containing 8 frames at 
     522                // 48 kHz) is the experimentally-determined figure for 48 
     523                // kHz with a period size of 1024.  It seems that at least 
     524                // one period of zero samples need to be sent to allow for 
     525                // inter-thread communication occuring on period boundaries.  
     526                // This needs to be confirmed for other rates and period 
     527                // sizes. 
     528                signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32); 
     529                m_closedown_count = m_period / n_events; 
     530 
     531                // Set up a test to confirm that streaming is still active. 
     532                // If the streaming function hasn't been called by the next 
     533                // iteration through this function there's no point in 
     534                // continuing since it means the zero data will never get to  
     535                // the MOTU. 
     536                m_streaming_active = 0; 
     537                return false; 
     538        } 
     539 
     540        // We are "go" for closedown once all requested zero packets 
     541        // (initiated by a previous call to this function) have been sent to 
     542        // the MOTU. 
     543        return m_closedown_count == 0; 
     544} 
     545 
     546bool MotuTransmitStreamProcessor::prepareForStart() { 
     547// Reset some critical variables required so the stream starts cleanly. This 
     548// method is called once on every stream restart. Initialisations which should  
     549// be done once should be placed in the init() method instead. 
     550        m_running = 0; 
     551        m_closedown_count = -1; 
     552        m_streaming_active = 0; 
     553 
     554        // At this point we'll also disable the stream processor here. 
     555        // At this stage stream processors are always explicitly re-enabled 
     556        // after being started, so by starting in the disabled state we  
     557        // ensure that every start will be exactly the same. 
     558        disable(); 
     559 
     560        return true; 
     561} 
     562 
     563bool MotuTransmitStreamProcessor::prepareForEnable(uint64_t time_to_enable_at) { 
     564 
     565    debugOutput(DEBUG_LEVEL_VERBOSE,"Preparing to enable...\n"); 
     566 
     567    // for the transmit SP, we have to initialize the  
     568    // buffer timestamp to something sane, because this timestamp 
     569    // is used when it is SyncSource 
     570     
     571    // the time we initialize to will determine the time at which 
     572    // the first sample in the buffer will be sent, so we should 
     573    // make it at least 'time_to_enable_at' 
     574     
     575    uint64_t now=m_handler->getCycleTimer(); 
     576    unsigned int now_secs=CYCLE_TIMER_GET_SECS(now); 
     577     
     578    // check if a wraparound on the secs will happen between 
     579    // now and the time we start 
     580    if (CYCLE_TIMER_GET_CYCLES(now)>time_to_enable_at) { 
     581        // the start will happen in the next second 
     582        now_secs++; 
     583        if (now_secs>=128) now_secs=0; 
     584    } 
     585     
     586    uint64_t ts_head= now_secs*TICKS_PER_SECOND; 
     587    ts_head+=time_to_enable_at*TICKS_PER_CYCLE; 
     588     
     589    // we also add the nb of cycles we transmit in advance 
     590    ts_head=addTicks(ts_head, TRANSMIT_ADVANCE_CYCLES*TICKS_PER_CYCLE); 
     591     
     592    m_data_buffer->setBufferTailTimestamp(ts_head); 
     593 
     594 
     595    if (!StreamProcessor::prepareForEnable(time_to_enable_at)) { 
     596        debugError("StreamProcessor::prepareForEnable failed\n"); 
     597        return false; 
     598    } 
     599 
     600    return true; 
     601} 
     602 
    494603bool MotuTransmitStreamProcessor::transferSilence(unsigned int size) { 
     604    bool retval; 
    495605     
    496606        // This function should tranfer 'size' frames of 'silence' to the event buffer 
    497         unsigned int write_size=size*m_event_size; 
    498607        char *dummybuffer=(char *)calloc(size,m_event_size); 
    499608 
    500609        transmitSilenceBlock(dummybuffer, size, 0); 
    501610 
    502         if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
    503                 debugWarning("Could not write to event buffer\n"); 
    504         } 
     611    // add the silence data to the ringbuffer 
     612    if(m_data_buffer->writeFrames(size, dummybuffer, 0)) {  
     613        retval=true; 
     614    } else { 
     615        debugWarning("Could not write to event buffer\n"); 
     616        retval=false; 
     617    } 
    505618 
    506619        free(dummybuffer); 
    507620 
    508         return true; 
    509 
    510  
    511 /** 
    512  * \brief write events queued for transmission from the port ringbuffers 
    513  * to the event buffer. 
    514  */ 
    515 bool MotuTransmitStreamProcessor::transfer() { 
    516         m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/m_event_size); 
    517  
    518         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
    519         // TODO: improve 
    520 /* a naive implementation would look like this: 
    521  
    522         unsigned int write_size=m_period*m_event_size; 
    523         char *dummybuffer=(char *)calloc(m_period,m_event_size); 
    524  
    525         transmitBlock(dummybuffer, m_period, 0, 0); 
    526  
    527         if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
    528                 debugWarning("Could not write to event buffer\n"); 
    529         } 
    530  
    531         free(dummybuffer); 
    532 */ 
    533 /* but we're not that naive anymore... */ 
    534         int xrun; 
    535         unsigned int offset=0; 
    536  
    537         freebob_ringbuffer_data_t vec[2]; 
    538         // There is one period of frames to transfer.  This is 
    539         // period_size*m_event_size of events. 
    540         unsigned int bytes2write=m_period*m_event_size; 
    541  
    542         /* Write bytes2write bytes to the event ringbuffer.  First see if it can 
    543          * be done in one write; if so, ok. 
    544          * Otherwise write up to a multiple of events directly to the buffer 
    545          * then do the buffer wrap around using ringbuffer_write.  Then 
    546          * write the remaining data directly to the buffer in a third pass.  
    547          * Make sure that we cannot end up on a non-cluster aligned 
    548          * position! 
    549          */ 
    550         while(bytes2write>0) { 
    551                 int byteswritten=0; 
    552          
    553                 unsigned int frameswritten=(m_period*m_event_size-bytes2write)/m_event_size; 
    554                 offset=frameswritten; 
    555  
    556                 freebob_ringbuffer_get_write_vector(m_event_buffer, vec); 
    557  
    558                 if (vec[0].len==0) { // this indicates a full event buffer 
    559                         debugError("XMT: Event buffer overrun in processor %p\n",this); 
    560                         break; 
    561                 } 
    562  
    563                 /* If we don't take care we will get stuck in an infinite 
    564                  * loop because we align to a event boundary later.  The 
    565                  * remaining nb of bytes in one write operation can be 
    566                  * smaller than one event; this can happen because the 
    567                  * ringbuffer size is always a power of 2. 
    568                  */ 
    569                 if(vec[0].len<m_event_size) { 
    570              
    571                         // encode to the temporary buffer 
    572                         xrun = transmitBlock(m_tmp_event_buffer, 1, offset); 
    573              
    574                         if (xrun<0) { 
    575                                 // xrun detected 
    576                                 debugError("XMT: Frame buffer underrun in processor %p\n",this); 
    577                                 break; 
    578                         } 
    579  
    580                         // Use the ringbuffer function to write one event. 
    581                         // The write function handles the wrap around. 
    582                         freebob_ringbuffer_write(m_event_buffer, 
    583                                 m_tmp_event_buffer, m_event_size); 
    584                  
    585                         // we advanced one m_event_size 
    586                         bytes2write-=m_event_size; 
    587                  
    588                 } else { 
    589              
    590                         if (bytes2write>vec[0].len) { 
    591                                 // align to an event boundary 
    592                                 byteswritten=vec[0].len-(vec[0].len%m_event_size); 
    593                         } else { 
    594                                 byteswritten=bytes2write; 
    595                         } 
    596  
    597                         xrun = transmitBlock(vec[0].buf, 
    598                                 byteswritten/m_event_size, offset); 
    599              
    600                         if (xrun<0) { 
    601                                 // xrun detected 
    602                                 debugError("XMT: Frame buffer underrun in processor %p\n",this); 
    603                                 break; 
    604                         } 
    605  
    606                         freebob_ringbuffer_write_advance(m_event_buffer, byteswritten); 
    607                         bytes2write -= byteswritten; 
    608                 } 
    609  
    610                 // the bytes2write should always be event aligned 
    611                 assert(bytes2write%m_event_size==0); 
    612         } 
    613  
    614         return true; 
    615 
     621        return retval; 
     622
     623 
     624bool MotuTransmitStreamProcessor::putFrames(unsigned int nbframes, int64_t ts) { 
     625    m_PeriodStat.mark(m_data_buffer->getBufferFill()); 
     626     
     627    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "MotuTransmitStreamProcessor::putFrames(%d, %llu)\n", nbframes, ts); 
     628     
     629    // transfer the data 
     630    m_data_buffer->blockProcessWriteFrames(nbframes, ts); 
     631 
     632    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " New timestamp: %llu\n", ts); 
     633 
     634    return true; 
     635
     636 
    616637/*  
    617638 * write received events to the stream ringbuffers. 
    618639 */ 
    619640 
    620 int MotuTransmitStreamProcessor::transmitBlock(char *data,  
     641bool MotuTransmitStreamProcessor::processWriteBlock(char *data,  
    621642                       unsigned int nevents, unsigned int offset) { 
    622         signed int problem=0
     643        bool no_problem=true
    623644        unsigned int i; 
    624645 
     
    641662                 
    642663                case Port::E_Audio: 
    643                         if (encodePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     664                        if (encodePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    644665                                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
    645                                 problem=1
     666                                no_problem=false
    646667                        } 
    647668                        break; 
     
    654675                } 
    655676        } 
    656         return problem; 
     677        return no_problem; 
    657678} 
    658679 
     
    673694                 
    674695                case Port::E_Audio: 
    675                         if (encodeSilencePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     696                        if (encodeSilencePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    676697                                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
    677698                                problem=1; 
     
    750771} 
    751772 
    752 int MotuTransmitStreamProcessor::encodePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,  
     773int MotuTransmitStreamProcessor::encodePortToMotuEvents(MotuAudioPort *p, quadlet_t *data,  
    753774                       unsigned int offset, unsigned int nevents) { 
    754775// Encodes nevents worth of data from the given port into the given buffer.  The 
     
    825846} 
    826847 
    827 int MotuTransmitStreamProcessor::encodeSilencePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,  
     848int MotuTransmitStreamProcessor::encodeSilencePortToMotuEvents(MotuAudioPort *p, quadlet_t *data,  
    828849                       unsigned int offset, unsigned int nevents) { 
    829850        unsigned int j=0; 
     
    844865} 
    845866 
    846 bool MotuTransmitStreamProcessor::prepareForStop() { 
    847  
    848         // If the stream is disabled or isn't running there's no need to 
    849         // wait since the MOTU *should* still be in a "zero data" state. 
    850         // 
    851         // If the m_streaming_active flag is 0 it indicates that the 
    852         // transmit callback hasn't been called since a closedown was 
    853         // requested when this function was last called.  This effectively 
    854         // signifies that the streaming thread has been exitted due to an 
    855         // xrun in either the receive or transmit handlers.  In this case 
    856         // there's no point in waiting for the closedown count to hit zero 
    857         // because it never will; the zero data will never get to the MOTU.  
    858         // It's best to allow an immediate stop and let the xrun handler 
    859         // proceed as best it can. 
    860         // 
    861         // The ability to detect the lack of streaming also prevents the 
    862         // "wait for stop" in the stream processor manager's stop() method 
    863         // from hitting its timeout which in turn seems to increase the 
    864         // probability of a successful recovery. 
    865         if (m_disabled || !isRunning() || !m_streaming_active) 
    866                 return true; 
    867  
    868         if (m_closedown_count < 0) { 
    869                 // No closedown has been initiated, so start one now.  Set 
    870                 // the closedown count to the number of zero packets which 
    871                 // will be sent to the MOTU before closing off the iso 
    872                 // streams.  FIXME: 128 packets (each containing 8 frames at 
    873                 // 48 kHz) is the experimentally-determined figure for 48 
    874                 // kHz with a period size of 1024.  It seems that at least 
    875                 // one period of zero samples need to be sent to allow for 
    876                 // inter-thread communication occuring on period boundaries.  
    877                 // This needs to be confirmed for other rates and period 
    878                 // sizes. 
    879                 signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32); 
    880                 m_closedown_count = m_period / n_events; 
    881  
    882                 // Set up a test to confirm that streaming is still active. 
    883                 // If the streaming function hasn't been called by the next 
    884                 // iteration through this function there's no point in 
    885                 // continuing since it means the zero data will never get to  
    886                 // the MOTU. 
    887                 m_streaming_active = 0; 
    888                 return false; 
    889         } 
    890  
    891         // We are "go" for closedown once all requested zero packets 
    892         // (initiated by a previous call to this function) have been sent to 
    893         // the MOTU. 
    894         return m_closedown_count == 0; 
    895 } 
    896  
    897 bool MotuTransmitStreamProcessor::prepareForStart() { 
    898 // Reset some critical variables required so the stream starts cleanly. This 
    899 // method is called once on every stream restart, including those during 
    900 // xrun recovery.  Initialisations which should be done once should be 
    901 // placed in the init() method instead. 
    902         m_running = 0; 
    903         m_next_cycle = -1; 
    904         m_closedown_count = -1; 
    905         m_streaming_active = 0; 
    906         m_cycle_count = -1; 
    907         m_cycle_ofs = 0.0; 
    908  
    909         // At this point we'll also disable the stream processor here. 
    910         // At this stage stream processors are always explicitly re-enabled 
    911         // after being started, so by starting in the disabled state we  
    912         // ensure that every start will be exactly the same. 
    913         disable(); 
    914  
    915         return true; 
    916 } 
    917  
    918867/* --------------------- RECEIVE ----------------------- */ 
    919868 
     
    921870        unsigned int event_size) 
    922871    : ReceiveStreamProcessor(port, framerate), m_event_size(event_size), 
    923         m_last_cycle_ofs(-1), m_next_cycle(-1), m_closedown_active(0) { 
    924  
    925         // Set up the Delay-locked-loop to track audio frequency relative 
    926         // to the cycle timer.  The seed value is the "ideal" value. 
    927         m_ticks_per_frame = 24576000.0/framerate; 
     872        m_closedown_active(0) { 
     873 
    928874} 
    929875 
    930876MotuReceiveStreamProcessor::~MotuReceiveStreamProcessor() { 
    931         freebob_ringbuffer_free(m_event_buffer); 
    932         free(m_tmp_event_buffer); 
     877 
    933878} 
    934879 
     
    946891} 
    947892 
    948 enum raw1394_iso_disposition  
    949 MotuReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,  
    950                   unsigned char channel, unsigned char tag, unsigned char sy,  
    951                   unsigned int cycle, unsigned int dropped) { 
    952      
    953         enum raw1394_iso_disposition retval=RAW1394_ISO_OK; 
    954         signed int have_lost_cycles = 0; 
    955  
     893        // NOTE by PP: timestamp based sync fixes this automagically by 
     894        //             enforcing that the roundtrip latency is constant: 
    956895        // Detect missed receive cycles 
    957896        // FIXME: it would be nice to advance the rx buffer by the amount of 
     
    961900        // were missed.  Ultimately I think we need to do so if sync is to 
    962901        // be maintained across a transient receive failure. 
    963         if (m_next_cycle < 0) 
    964                 m_next_cycle = cycle; 
    965         if ((signed)cycle != m_next_cycle) { 
    966                 debugOutput(DEBUG_LEVEL_VERBOSE, "lost rx cycles; received %d, expected %d\n", 
    967                         cycle, m_next_cycle); 
    968                 m_next_cycle = cycle; 
    969                 have_lost_cycles = 1; 
    970         } 
    971         if (++m_next_cycle >= 8000) 
    972                 m_next_cycle -= 8000; 
    973  
     902         
     903enum raw1394_iso_disposition  
     904MotuReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,  
     905                  unsigned char channel, unsigned char tag, unsigned char sy,  
     906                  unsigned int cycle, unsigned int dropped) { 
     907     
     908        enum raw1394_iso_disposition retval=RAW1394_ISO_OK; 
     909        // this is needed for the base class getLastCycle() to work. 
     910        // this avoids a function call like StreamProcessor::updateLastCycle() 
     911    m_last_cycle=cycle; 
     912 
     913    // check our enable status 
     914    if (!m_disabled && m_is_disabled) { 
     915        // this means that we are trying to enable 
     916        if (cycle == m_cycle_to_enable_at) { 
     917            m_is_disabled=false; 
     918            debugOutput(DEBUG_LEVEL_VERBOSE,"Enabling StreamProcessor %p at %d\n",  
     919                this, cycle); 
     920                 
     921            // the previous timestamp is the one we need to start with 
     922            // because we're going to update the buffer again this loop 
     923            // using writeframes 
     924            m_data_buffer->setBufferTailTimestamp(m_last_timestamp2); 
     925 
     926        } else { 
     927            debugOutput(DEBUG_LEVEL_VERY_VERBOSE, 
     928                "will enable StreamProcessor %p at %u, now is %d\n", 
     929                    this, m_cycle_to_enable_at, cycle); 
     930        } 
     931    } else if (m_disabled && !m_is_disabled) { 
     932        // trying to disable 
     933        debugOutput(DEBUG_LEVEL_VERBOSE,"disabling StreamProcessor %p at %u\n", this, cycle); 
     934        m_is_disabled=true; 
     935    } 
     936         
    974937        // If the packet length is 8 bytes (ie: just a CIP-like header) 
    975938        // there is no isodata. 
     
    981944                unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size 
    982945                unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits 
    983                 unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes 
    984                 unsigned int n_events = (length-8) / event_length; 
    985946 
    986947                // Don't even attempt to process a packet if it isn't what 
     
    992953                        return RAW1394_ISO_OK; 
    993954                } 
     955                 
     956                // put this after the check because event_length can become 0 on invalid packets 
     957                unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes 
     958                unsigned int n_events = (length-8) / event_length; 
     959                 
     960        //=> store the previous timestamp 
     961        m_last_timestamp2=m_last_timestamp; 
     962 
     963        //=> convert the SYT to a full timestamp in ticks 
     964        m_last_timestamp=sytRecvToFullTicks((uint32_t)ntohl(*(quadlet_t *)(data+8)),  
     965                                        cycle, m_handler->getCycleTimer()); 
    994966 
    995967                // Signal that we're running 
    996                 if (n_events) m_running=true; 
    997  
    998                 /* Send actual ticks-per-frame values (as deduced by the 
    999                  * incoming SPHs) to the DLL for averaging.  Doing this here 
    1000                  * means the DLL should acquire a reasonable estimation of 
    1001                  * the ticks per frame even while the stream is formally 
    1002                  * disabled.  This in turn means the transmit stream should 
    1003                  * have access to a very realistic estimate by the time it 
    1004                  * is enabled.  The major disadvantage is a small increase 
    1005                  * in the overheads of this function compared to what would 
    1006                  * be the case if this was delayed by pushing it into the 
    1007                  * decode functions. 
    1008                  */ 
    1009                 unsigned int ev; 
    1010                 signed int sph_ofs; 
    1011  
    1012                 /* If this is the first block received or we have lost 
    1013                  * cycles, initialise the m_last_cycle_ofs to a value which 
    1014                  * won't cause the DLL to become polluted with an 
    1015                  * inappropriate ticks-per-frame estimate. 
    1016                  */ 
    1017                 if (m_last_cycle_ofs<0 || have_lost_cycles) { 
    1018                         sph_ofs = ntohl(*(quadlet_t *)(data+8)) & 0xfff; 
    1019                         m_last_cycle_ofs = sph_ofs-(int)(m_ticks_per_frame); 
    1020                 } 
    1021                 for (ev=0; ev<n_events; ev++) { 
    1022                         sph_ofs = ntohl(*(quadlet_t *)(data+8+ev*m_event_size)) & 0xfff; 
    1023                         signed int sph_diff = (sph_ofs - m_last_cycle_ofs); 
    1024                         // Handle wraparound of the cycle offset 
    1025                         if (sph_diff < 0) 
    1026                                 sph_diff += 3072; 
    1027                         float err = sph_diff - m_ticks_per_frame; 
    1028                         // FIXME: originally we used a value of 0.0005 for 
    1029                         // the coefficient which mirrored the value used in 
    1030                         // AmdtpReceiveStreamProcessor::putPacket() for a 
    1031                         // similar purpose.  However, tests showed that this 
    1032                         // introduced discontinuities in the output audio 
    1033                         // signal, so an alternative value was sought.  
    1034                         // Further tests are needed, but a value of 0.015 
    1035                         // seems to work well, at least at a sample rate of 
    1036                         // 48 kHz. 
    1037                         m_ticks_per_frame += 0.015*err; 
    1038                         m_last_cycle_ofs = sph_ofs; 
    1039                 } 
    1040  
    1041                 // Don't process the stream when it is not enabled 
    1042                 if (m_disabled) { 
    1043                         return RAW1394_ISO_OK; 
    1044                 } 
    1045  
    1046                 // If closedown is active we also just throw data way, but 
    1047                 // in this case we keep the frame counter going to prevent a 
    1048                 // false xrun detection 
    1049                 if (m_closedown_active) { 
    1050                         incrementFrameCounter(n_events); 
    1051                         if (m_framecounter > (signed int)m_period) 
    1052                                 return RAW1394_ISO_DEFER; 
    1053                         return RAW1394_ISO_OK; 
    1054                 } 
     968        if(!m_running && n_events && m_last_timestamp2 && m_last_timestamp) { 
     969            debugOutput(DEBUG_LEVEL_VERBOSE,"Receive StreamProcessor %p started running at %d\n", this, cycle); 
     970            m_running=true; 
     971        } 
     972 
     973        //=> don't process the stream samples when it is not enabled. 
     974        if(m_is_disabled) { 
     975 
     976            // we keep track of the timestamp here 
     977            // this makes sure that we will have a somewhat accurate 
     978            // estimate as to when a period might be ready. i.e. it will not 
     979            // be ready earlier than this timestamp + period time 
     980             
     981            // the next (possible) sample is not this one, but lies  
     982            // SYT_INTERVAL * rate later 
     983            float frame_size=m_framerate<=48000?8:(m_framerate<=96000?16:32); 
     984            uint64_t ts=addTicks(m_last_timestamp, 
     985                                 (uint64_t)(frame_size * m_ticks_per_frame)); 
     986 
     987            // set the timestamp as if there will be a sample put into 
     988            // the buffer by the next packet. 
     989            m_data_buffer->setBufferTailTimestamp(ts); 
     990             
     991            return RAW1394_ISO_DEFER; 
     992        } 
    1055993 
    1056994                debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "put packet...\n"); 
    1057995 
    1058                 // Add the data payload (events) to the ringbuffer.  We'll 
    1059                 // just copy everything including the 4 byte timestamp at 
    1060                 // the start of each event (that is, everything except the 
    1061                 // CIP-like header).  The demultiplexer can deal with the 
    1062                 // complexities such as the channel 24-bit data. 
    1063                 unsigned int write_size = length-8; 
    1064                 if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size) { 
    1065                         debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",  
    1066                                 cycle, m_framecounter, m_handler->getPacketCount()); 
    1067                         m_xruns++; 
    1068  
    1069                         retval=RAW1394_ISO_DEFER; 
    1070                 } else { 
    1071                         retval=RAW1394_ISO_OK; 
    1072                         // Process all ports that should be handled on a 
    1073                         // per-packet basis.  This is MIDI for AMDTP (due to 
    1074                         // the need of DBC) 
    1075                         int dbc = get_bits(ntohl(quadlet[0]), 8, 8);  // Low byte of CIP quadlet 0 
    1076                         if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) { 
    1077                                 debugWarning("Problem decoding Packet Ports\n"); 
    1078                                 retval=RAW1394_ISO_DEFER; 
    1079                         } 
    1080                         // time stamp processing can be done here 
    1081                 } 
    1082  
    1083                 // update the frame counter 
    1084                 incrementFrameCounter(n_events); 
    1085                 // keep this at the end, because otherwise the 
    1086                 // raw1394_loop_iterate functions inner loop keeps 
    1087                 // requesting packets without going to the xmit handler, 
    1088                 // leading to xmit starvation 
    1089                 if(m_framecounter>(signed int)m_period) { 
    1090                         retval=RAW1394_ISO_DEFER; 
    1091                 } 
    1092  
    1093         } else { // no events in packet 
    1094                 // discard packet 
    1095                 // can be important for sync though 
    1096         } 
    1097      
     996        //=> process the packet 
     997        // add the data payload to the ringbuffer 
     998        if(m_data_buffer->writeFrames(n_events, (char *)(data+8), m_last_timestamp)) {  
     999            retval=RAW1394_ISO_OK; 
     1000             
     1001            int dbc = get_bits(ntohl(quadlet[0]), 8, 8); 
     1002             
     1003            // process all ports that should be handled on a per-packet base 
     1004            // this is MIDI for AMDTP (due to the need of DBC) 
     1005            if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) { 
     1006                debugWarning("Problem decoding Packet Ports\n"); 
     1007                retval=RAW1394_ISO_DEFER; 
     1008            } 
     1009             
     1010        } else { 
     1011         
     1012            debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",  
     1013                 cycle, m_data_buffer->getFrameCounter(), m_handler->getPacketCount()); 
     1014             
     1015            m_xruns++; 
     1016             
     1017            // disable the processing, will be re-enabled when 
     1018            // the xrun is handled 
     1019            m_disabled=true; 
     1020            m_is_disabled=true; 
     1021 
     1022            retval=RAW1394_ISO_DEFER; 
     1023        } 
     1024    } 
     1025 
    10981026        return retval; 
    10991027} 
    11001028 
    1101 bool MotuReceiveStreamProcessor::isOnePeriodReady() {  
    1102      // TODO: this is the way you can implement sync 
    1103      //       only when this returns true, one period will be 
    1104      //       transferred to the audio api side. 
    1105      //       you can delay this moment as long as you 
    1106      //       want (provided that there is enough buffer space) 
    1107       
    1108      // this implementation just waits until there is one period of samples 
    1109      // received into the buffer 
    1110     if(m_framecounter > (signed int)m_period) { 
    1111         return true; 
    1112     } 
    1113     return false; 
    1114 
    1115  
    1116 void MotuReceiveStreamProcessor::setVerboseLevel(int l) { 
    1117         setDebugLevel(l); 
    1118         ReceiveStreamProcessor::setVerboseLevel(l); 
    1119  
    1120 
    1121  
     1029// returns the delay between the actual (real) time of a timestamp as received, 
     1030// and the timestamp that is passed on for the same event. This is to cope with 
     1031// ISO buffering 
     1032int MotuReceiveStreamProcessor::getMinimalSyncDelay() { 
     1033        unsigned int n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32); 
     1034     
     1035    return (int)(m_handler->getWakeupInterval() * n_events * m_ticks_per_frame); 
     1036
    11221037 
    11231038bool MotuReceiveStreamProcessor::reset() { 
    11241039 
    11251040        debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n"); 
    1126  
    1127         // reset the event buffer, discard all content 
    1128         freebob_ringbuffer_reset(m_event_buffer); 
     1041         
     1042    // this makes that the buffer lags a little compared to reality 
     1043    // the result is that we get some extra time before period boundaries 
     1044    // are signaled. 
     1045    // ISO buffering causes the packets to be received at max 
     1046    // m_handler->getWakeupInterval() later than the time they were received. 
     1047    // hence their payload is available this amount of time later. However, the 
     1048    // period boundary is predicted based upon earlier samples, and therefore can 
     1049    // pass before these packets are processed. Adding this extra term makes that 
     1050    // the period boundary is signalled later 
     1051    m_data_buffer->setTickOffset(m_SyncSource->getSyncDelay()); 
    11291052 
    11301053        // reset all non-device specific stuff 
     
    11351058        } 
    11361059 
    1137         m_next_cycle = -1; 
    1138  
    11391060        return true; 
    11401061} 
     
    11561077 
    11571078    // setup any specific stuff here 
    1158  
     1079    // FIXME: m_frame_size would be a better name 
    11591080        debugOutput( DEBUG_LEVEL_VERBOSE, "Event size: %d\n", m_event_size); 
    11601081     
    1161         // allocate the event buffer 
     1082    // prepare the framerate estimate 
     1083    float ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate); 
     1084         
     1085        // initialize internal buffer 
    11621086        unsigned int ringbuffer_size_frames=m_nb_buffers * m_period; 
    1163  
    1164         if( !(m_event_buffer=freebob_ringbuffer_create( 
    1165                         m_event_size * ringbuffer_size_frames))) { 
    1166                 debugFatal("Could not allocate memory event ringbuffer"); 
    1167                 return false; 
    1168         } 
    1169  
    1170         // allocate the temporary event buffer 
    1171         if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) { 
    1172                 debugFatal("Could not allocate temporary event buffer"); 
    1173                 freebob_ringbuffer_free(m_event_buffer); 
    1174                 return false; 
    1175         } 
     1087         
     1088        unsigned int events_per_frame = m_framerate<=48000?8:(m_framerate<=96000?16:32); 
     1089 
     1090    assert(m_data_buffer);     
     1091    m_data_buffer->setBufferSize(ringbuffer_size_frames); 
     1092    m_data_buffer->setEventSize(m_event_size/events_per_frame); 
     1093    m_data_buffer->setEventsPerFrame(events_per_frame);  
     1094     
     1095    m_data_buffer->setUpdatePeriod(m_period); 
     1096    m_data_buffer->setNominalRate(ticks_per_frame); 
     1097     
     1098    m_data_buffer->setWrapValue(TICKS_PER_SECOND); 
     1099     
     1100    m_data_buffer->prepare(); 
    11761101 
    11771102        // set the parameters of ports we can: 
     
    12411166} 
    12421167 
    1243 bool MotuReceiveStreamProcessor::transfer() { 
    1244  
    1245     // the same idea as the transmit processor 
    1246      
    1247         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
    1248          
    1249 /* another naive section:        
    1250         unsigned int read_size=m_period*m_event_size; 
    1251         char *dummybuffer=(char *)calloc(m_period,m_event_size); 
    1252         if (freebob_ringbuffer_read(m_event_buffer,(char *)(dummybuffer),read_size) < read_size) { 
    1253                 debugWarning("Could not read from event buffer\n"); 
    1254         } 
    1255  
    1256         receiveBlock(dummybuffer, m_period, 0); 
    1257  
    1258         free(dummybuffer); 
    1259 */ 
    1260         int xrun; 
    1261         unsigned int offset=0; 
    1262          
    1263         freebob_ringbuffer_data_t vec[2]; 
    1264         // We received one period of frames from each channel. 
    1265         // This is period_size*m_event_size bytes. 
    1266         unsigned int bytes2read = m_period * m_event_size; 
    1267  
    1268         // If closedown is in progress just pretend that data's been transferred 
    1269         // to prevent false underrun detections on the event buffer. 
    1270         if (m_closedown_active) 
    1271                 return true; 
    1272  
    1273         /* Read events2read bytes from the ringbuffer. 
    1274         *  First see if it can be done in one read.  If so, ok. 
    1275         *  Otherwise read up to a multiple of events directly from the buffer 
    1276         *  then do the buffer wrap around using ringbuffer_read 
    1277         *  then read the remaining data directly from the buffer in a third pass  
    1278         *  Make sure that we cannot end up on a non-event aligned position! 
    1279         */ 
    1280         while(bytes2read>0) { 
    1281                 unsigned int framesread=(m_period*m_event_size-bytes2read)/m_event_size; 
    1282                 offset=framesread; 
    1283                  
    1284                 int bytesread=0; 
    1285  
    1286                 freebob_ringbuffer_get_read_vector(m_event_buffer, vec); 
    1287                          
    1288                 if(vec[0].len==0) { // this indicates an empty event buffer 
    1289                         debugError("RCV: Event buffer underrun in processor %p\n",this); 
    1290                         break; 
    1291                 } 
    1292                          
    1293                 /* if we don't take care we will get stuck in an infinite loop 
    1294                 * because we align to an event boundary later 
    1295                 * the remaining nb of bytes in one read operation can be smaller than one event 
    1296                 * this can happen because the ringbuffer size is always a power of 2 
    1297                 */ 
    1298                 if(vec[0].len<m_event_size) { 
    1299                         // use the ringbuffer function to read one event  
    1300                         // the read function handles wrap around 
    1301                         freebob_ringbuffer_read(m_event_buffer,m_tmp_event_buffer,m_event_size); 
    1302  
    1303                         xrun = receiveBlock(m_tmp_event_buffer, 1, offset); 
    1304                                  
    1305                         if(xrun<0) { 
    1306                                 // xrun detected 
    1307                                 debugError("RCV: Frame buffer overrun in processor %p\n",this); 
    1308                                 break; 
    1309                         } 
    1310                                  
    1311                         // We advanced one m_event_size 
    1312                         bytes2read-=m_event_size; 
    1313                                  
    1314                 } else { //  
    1315                          
    1316                         if(bytes2read>vec[0].len) { 
    1317                                         // align to an event boundary 
    1318                                 bytesread=vec[0].len-(vec[0].len%m_event_size); 
    1319                         } else { 
    1320                                 bytesread=bytes2read; 
    1321                         } 
    1322                                  
    1323                         xrun = receiveBlock(vec[0].buf, bytesread/m_event_size, offset); 
    1324                                  
    1325                         if(xrun<0) { 
    1326                                 // xrun detected 
    1327                                 debugError("RCV: Frame buffer overrun in processor %p\n",this); 
    1328                                 break; 
    1329                         } 
    1330  
    1331                         freebob_ringbuffer_read_advance(m_event_buffer, bytesread); 
    1332                         bytes2read -= bytesread; 
    1333                 } 
    1334                          
    1335                 // the bytes2read should always be event aligned 
    1336                 assert(bytes2read%m_event_size==0); 
    1337         } 
    1338  
     1168 
     1169bool MotuReceiveStreamProcessor::prepareForStop() { 
     1170 
     1171        // A MOTU receive stream can stop at any time.  However, signify 
     1172        // that stopping is in progress because other streams (notably the 
     1173        // transmit stream) may keep going for some time and cause an 
     1174        // overflow in the receive buffers.  If a closedown is in progress 
     1175        // the receive handler simply throws all incoming data away so 
     1176        // no buffer overflow can occur. 
     1177        m_closedown_active = 1; 
    13391178        return true; 
     1179} 
     1180 
     1181bool MotuReceiveStreamProcessor::prepareForStart() { 
     1182// Reset some critical variables required so the stream starts cleanly. This 
     1183// method is called once on every stream restart, including those during 
     1184// xrun recovery.  Initialisations which should be done once should be 
     1185// placed in the init() method instead. 
     1186        m_running = 0; 
     1187        m_closedown_active = 0; 
     1188 
     1189        // At this point we'll also disable the stream processor here. 
     1190        // At this stage stream processors are always explicitly re-enabled 
     1191        // after being started, so by starting in the disabled state we  
     1192        // ensure that every start will be exactly the same. 
     1193        disable(); 
     1194 
     1195        return true; 
     1196} 
     1197 
     1198bool MotuReceiveStreamProcessor::getFrames(unsigned int nbframes) { 
     1199 
     1200    m_PeriodStat.mark(m_data_buffer->getBufferFill()); 
     1201 
     1202    // ask the buffer to process nbframes of frames 
     1203    // using it's registered client's processReadBlock(), 
     1204    // which should be ours 
     1205    m_data_buffer->blockProcessReadFrames(nbframes); 
     1206 
     1207    return true; 
    13401208} 
    13411209 
     
    13431211 * \brief write received events to the port ringbuffers. 
    13441212 */ 
    1345 int MotuReceiveStreamProcessor::receiveBlock(char *data,  
     1213bool MotuReceiveStreamProcessor::processReadBlock(char *data,  
    13461214                                           unsigned int nevents, unsigned int offset) 
    13471215{ 
    1348         int problem=0
     1216        bool no_problem=true
    13491217        for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    13501218          it != m_PeriodPorts.end(); 
     
    13581226                 
    13591227                case Port::E_Audio: 
    1360                         if(decodeMBLAEventsToPort(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     1228                        if(decodeMotuEventsToPort(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    13611229                                debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str()); 
    1362                                 problem=1
     1230                                no_problem=false
    13631231                        } 
    13641232                        break; 
     
    13711239                } 
    13721240        } 
    1373         return problem; 
     1241        return no_problem; 
    13741242} 
    13751243 
     
    14411309} 
    14421310 
    1443 signed int MotuReceiveStreamProcessor::decodeMBLAEventsToPort(MotuAudioPort *p,  
     1311signed int MotuReceiveStreamProcessor::decodeMotuEventsToPort(MotuAudioPort *p,  
    14441312                quadlet_t *data, unsigned int offset, unsigned int nevents) 
    14451313{ 
     
    15241392} 
    15251393 
    1526 bool MotuReceiveStreamProcessor::prepareForStop() { 
    1527  
    1528         // A MOTU receive stream can stop at any time.  However, signify 
    1529         // that stopping is in progress because other streams (notably the 
    1530         // transmit stream) may keep going for some time and cause an 
    1531         // overflow in the receive buffers.  If a closedown is in progress 
    1532         // the receive handler simply throws all incoming data away so 
    1533         // no buffer overflow can occur. 
    1534         m_closedown_active = 1; 
    1535         return true; 
    1536 
    1537  
    1538 bool MotuReceiveStreamProcessor::prepareForStart() { 
    1539 // Reset some critical variables required so the stream starts cleanly. This 
    1540 // method is called once on every stream restart, including those during 
    1541 // xrun recovery.  Initialisations which should be done once should be 
    1542 // placed in the init() method instead. 
    1543         m_running = 0; 
    1544         m_next_cycle = -1; 
    1545         m_closedown_active = 0; 
    1546         m_last_cycle_ofs = -1; 
    1547  
    1548         // At this point we'll also disable the stream processor here. 
    1549         // At this stage stream processors are always explicitly re-enabled 
    1550         // after being started, so by starting in the disabled state we  
    1551         // ensure that every start will be exactly the same. 
    1552         disable(); 
    1553  
    1554         return true; 
    1555 
    1556  
    1557                  
     1394void MotuReceiveStreamProcessor::setVerboseLevel(int l) { 
     1395        setDebugLevel(l); 
     1396        ReceiveStreamProcessor::setVerboseLevel(l); 
     1397
     1398 
    15581399} // end of namespace FreebobStreaming 
    15591400#endif 
  • branches/streaming-rework/src/libstreaming/MotuStreamProcessor.h

    r384 r402  
    6464        bool reset(); 
    6565        bool prepare(); 
    66         bool transfer(); 
     66 
     67        bool prepareForStop(); 
     68        bool prepareForStart(); 
    6769         
    68         bool isOnePeriodReady(); 
    69  
     70    bool prepareForEnable(uint64_t time_to_enable_at); 
     71     
     72    bool putFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents from the client 
     73         
    7074        // These two are important to calculate the optimal ISO DMA buffers 
    7175        // size.  An estimate will do. 
     
    7377        unsigned int getMaxPacketSize() {return m_framerate<=48000?616:(m_framerate<=96000?1032:1160);};  
    7478 
    75        virtual void setVerboseLevel(int l); 
     79    int getMinimalSyncDelay(); 
    7680 
    77         void setTicksPerFrameDLL(float *dll) {m_ticks_per_frame=dll;}; 
    78  
    79         virtual bool prepareForStop(); 
    80         virtual bool prepareForStart(); 
     81        void setVerboseLevel(int l); 
    8182 
    8283protected: 
    83  
    84         freebob_ringbuffer_t * m_event_buffer; 
    85         char* m_tmp_event_buffer; 
    86          
    8784        /* 
    8885         * An iso packet mostly consists of multiple events.  m_event_size 
     
    9491        unsigned int m_tx_dbc; 
    9592 
    96         // Transmission cycle count and cycle offset 
    97         signed int m_cycle_count; 
    98         float m_cycle_ofs; 
    99  
    100         // Used to detect missed cycles 
    101         signed int m_next_cycle; 
    102  
    103         // Hook to the DLL in the receive stream which provides a 
    104         // continuously updated estimate of the number of ieee1394 ticks 
    105         // per audio frame. 
    106         float *m_ticks_per_frame; 
    107  
    10893        // Used to keep track of the close-down zeroing of output data 
    10994        signed int m_closedown_count; 
     
    11499        bool transferSilence(unsigned int size); 
    115100 
    116         int transmitBlock(char *data, unsigned int nevents,  
    117                           unsigned int offset); 
    118                            
     101    bool processWriteBlock(char *data, unsigned int nevents, unsigned int offset); 
     102 
    119103        bool encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc); 
    120104         
     
    122106                          unsigned int offset); 
    123107                           
    124         int encodePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,  
     108        int encodePortToMotuEvents(MotuAudioPort *p, quadlet_t *data,  
    125109                unsigned int offset, unsigned int nevents); 
    126         int encodeSilencePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,  
     110        int encodeSilencePortToMotuEvents(MotuAudioPort *p, quadlet_t *data,  
    127111                unsigned int offset, unsigned int nevents); 
    128112 
     
    147131                      unsigned char channel, unsigned char tag, unsigned char sy,  
    148132                          unsigned int cycle, unsigned int dropped); 
     133                           
     134    bool getFrames(unsigned int nbframes); ///< transfer the buffer contents to the client 
    149135         
    150136        bool init(); 
    151137        bool reset(); 
    152138        bool prepare(); 
    153         bool transfer(); 
    154          
    155         bool isOnePeriodReady(); 
    156139 
    157140    // these two are important to calculate the optimal 
     
    160143        unsigned int getPacketsPerPeriod() {return (m_period*8000) / m_framerate;}; 
    161144        unsigned int getMaxPacketSize() {return m_framerate<=48000?616:(m_framerate<=96000?1032:1160);};  
     145     
     146    int getMinimalSyncDelay(); 
    162147 
    163148        virtual void setVerboseLevel(int l); 
    164149         
    165         float *getTicksPerFrameDLL(void) {return &m_ticks_per_frame;}; 
    166150        signed int setEventSize(unsigned int size); 
    167151        unsigned int getEventSize(void); 
     
    172156protected: 
    173157 
    174         int receiveBlock(char *data, unsigned int nevents, unsigned int offset); 
     158        bool processReadBlock(char *data, unsigned int nevents, unsigned int offset); 
     159         
    175160        bool decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc); 
    176         signed int decodeMBLAEventsToPort(MotuAudioPort *p, quadlet_t *data, unsigned int offset, unsigned int nevents); 
     161        signed int decodeMotuEventsToPort(MotuAudioPort *p, quadlet_t *data, unsigned int offset, unsigned int nevents); 
    177162 
    178         freebob_ringbuffer_t * m_event_buffer; 
    179         char* m_tmp_event_buffer; 
    180          
    181163        /* 
    182164         * An iso packet mostly consists of multiple events.  m_event_size 
     
    185167        unsigned int m_event_size; 
    186168 
    187         signed int m_last_cycle_ofs; 
    188         signed int m_next_cycle; 
    189  
    190169        // Signifies a closedown is in progress, in which case incoming data  
    191170        // is junked. 
    192171        signed int m_closedown_active; 
    193  
     172         
     173    uint64_t m_last_timestamp; /// last timestamp (in ticks) 
     174    uint64_t m_last_timestamp2; /// last timestamp (in ticks) 
     175    uint64_t m_last_timestamp_at_period_ticks; 
     176     
    194177    DECLARE_DEBUG_MODULE; 
    195178 
  • branches/streaming-rework/src/motu/motu_avdevice.cpp

    r384 r402  
    501501        } 
    502502 
    503         // Connect the transmit stream ticks-per-frame hook to the 
    504         // ticks-per-frame DLL integrator in the receive stream. 
    505         m_transmitProcessor->setTicksPerFrameDLL(m_receiveProcessor->getTicksPerFrameDLL()); 
    506  
    507503        // Now we add ports to the processor 
    508504        debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");