Changeset 1536

Show
Ignore:
Timestamp:
04/12/09 14:12:33 (12 years ago)
Author:
ppalmers
Message:

introduce transmit prebuffering to increase reliability

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/libffado-2.0/config.h.in

    r1529 r1536  
    182182// more robust. It should be noted though that shifting the transfer 
    183183// time to a later time instant also causes the xmit buffer fill to be 
    184 // lower on average. 
     184// lower on average. This can be counteracted by increasing the 
     185// STREAMPROCESSORMANAGER_XMIT_PREBUFFER_FRAMES option 
    185186#define STREAMPROCESSORMANAGER_SIGNAL_DELAY_TICKS           (3072*0) 
     187 
     188// the number of frames that we prebuffer in the 1394 ISO layer 
     189// this adds directly to the roundtrip latency 
     190#define STREAMPROCESSORMANAGER_XMIT_PREBUFFER_FRAMES         100 
    186191 
    187192// causes the waitForPeriod() call to wait until sufficient 
  • branches/libffado-2.0/src/libieee1394/IsoHandlerManager.cpp

    r1526 r1536  
    267267 
    268268        if(no_one_to_poll) { 
    269             debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, 
     269            debugOutputExtreme(DEBUG_LEVEL_VERBOSE, 
    270270                        "(%p, %s) No one to poll, waiting for something to happen\n", 
    271271                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive")); 
  • branches/libffado-2.0/src/libstreaming/generic/StreamProcessor.cpp

    r1530 r1536  
    7777    , m_ticks_per_frame( 0 ) 
    7878    , m_dll_bandwidth_hz ( STREAMPROCESSOR_DLL_BW_HZ ) 
    79     , m_sync_delay_frames( 0 ) 
     79    , m_extra_buffer_frames( 0 ) 
    8080    , m_in_xrun( false ) 
    8181{ 
     
    130130    m_in_xrun = true; 
    131131    SIGNAL_ACTIVITY_ALL; 
    132 } 
    133  
    134 uint64_t StreamProcessor::getTimeNow() { 
    135     return m_1394service.getCycleTimerTicks(); 
    136132} 
    137133 
     
    172168 * Buffer management and manipulation          * 
    173169 ***********************************************/ 
     170void 
     171StreamProcessor::getBufferHeadTimestamp(ffado_timestamp_t *ts, signed int *fc) 
     172{ 
     173    m_data_buffer->getBufferHeadTimestamp(ts, fc); 
     174} 
     175 
     176void 
     177StreamProcessor::getBufferTailTimestamp(ffado_timestamp_t *ts, signed int *fc) 
     178{ 
     179    m_data_buffer->getBufferTailTimestamp(ts, fc); 
     180} 
     181 
     182void StreamProcessor::setBufferTailTimestamp(ffado_timestamp_t new_timestamp) 
     183{ 
     184    m_data_buffer->setBufferTailTimestamp(new_timestamp); 
     185} 
     186 
     187void 
     188StreamProcessor::setBufferHeadTimestamp(ffado_timestamp_t new_timestamp) 
     189{ 
     190    m_data_buffer->setBufferHeadTimestamp(new_timestamp); 
     191} 
    174192 
    175193int StreamProcessor::getBufferFill() { 
     
    177195} 
    178196 
    179 int64_t 
    180 StreamProcessor::getTimeUntilNextPeriodSignalUsecs() 
    181 { 
    182     uint64_t time_at_period=getTimeAtPeriod(); 
    183  
    184     // we delay the period signal with the sync delay 
    185     // this makes that the period signals lag a little compared to reality 
    186     // ISO buffering causes the packets to be received at max 
    187     // m_handler->getWakeupInterval() later than the time they were received. 
    188     // hence their payload is available this amount of time later. However, the 
    189     // period boundary is predicted based upon earlier samples, and therefore can 
    190     // pass before these packets are processed. Adding this extra term makes that 
    191     // the period boundary is signalled later 
    192     time_at_period = addTicks(time_at_period, m_StreamProcessorManager.getSyncSource().getSyncDelay()); 
    193  
    194     uint64_t cycle_timer=m_1394service.getCycleTimerTicks(); 
    195  
    196     // calculate the time until the next period 
    197     int32_t until_next=diffTicks(time_at_period,cycle_timer); 
    198  
    199     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TAP=%11llu, CTR=%11llu, UTN=%11ld\n", 
    200         time_at_period, cycle_timer, until_next 
    201         ); 
    202  
    203     // now convert to usecs 
    204     // don't use the mapping function because it only works 
    205     // for absolute times, not the relative time we are 
    206     // using here (which can also be negative). 
    207     return (int64_t)(((float)until_next) / TICKS_PER_USEC); 
    208 } 
    209  
    210197void 
    211 StreamProcessor::setSyncDelay(unsigned int ticks) { 
    212  
    213     // round the sync delay to an integer number of packets now we know the frame rate 
    214     int frames = (int)((float)ticks / getTicksPerFrame()); 
    215     frames = (frames / getNominalFramesPerPacket()) + 1; 
    216     frames *= getNominalFramesPerPacket(); 
    217      
    218     #ifdef DEBUG 
    219     float ticks2 = frames * getTicksPerFrame(); 
    220     debugOutput(DEBUG_LEVEL_VERBOSE, "Setting SP %p SyncDelay to %u ticks => rounded to %u frames, %f ticks\n", 
    221                 this, ticks, frames, ticks2); 
    222     #endif 
    223     m_sync_delay_frames = frames; 
     198StreamProcessor::setExtraBufferFrames(unsigned int frames) { 
     199    debugOutput(DEBUG_LEVEL_VERBOSE, "Setting extra buffer to %d frames\n", frames); 
     200    m_extra_buffer_frames = frames; 
    224201} 
    225202 
    226203unsigned int 
    227 StreamProcessor::getSyncDelayFrames() { 
    228     return m_sync_delay_frames; 
    229 
    230  
    231 unsigned int 
    232 StreamProcessor::getSyncDelay() { 
    233     return (unsigned int)(m_sync_delay_frames * getTicksPerFrame()); 
     204StreamProcessor::getExtraBufferFrames() { 
     205    return m_extra_buffer_frames; 
    234206} 
    235207 
    236208uint64_t 
    237 StreamProcessor::getTimeAtPeriodUsecs() 
    238 
    239     return (uint64_t)((float)getTimeAtPeriod() * TICKS_PER_USEC); 
    240 
    241  
    242 uint64_t 
    243 StreamProcessor::getTimeAtPeriod()  
     209StreamProcessor::getTimeAtPeriod() 
    244210{ 
    245211    if (getType() == ePT_Receive) { 
     
    517483                return RAW1394_ISO_ERROR; 
    518484            } 
     485 
     486            // don't process the data when waiting for a stream 
     487            if(m_state == ePS_WaitingForStream) { 
     488                return RAW1394_ISO_OK; 
     489            } 
    519490        } 
    520491 
     
    13791350StreamProcessor::doStop() 
    13801351{ 
     1352    assert(m_data_buffer); 
     1353 
    13811354    float ticks_per_frame; 
    1382     unsigned int ringbuffer_size_frames = (m_StreamProcessorManager.getNbBuffers() + 1) * m_StreamProcessorManager.getPeriodSize(); 
     1355    unsigned int ringbuffer_size_frames = m_StreamProcessorManager.getNbBuffers() * m_StreamProcessorManager.getPeriodSize(); 
     1356    ringbuffer_size_frames += m_extra_buffer_frames; 
     1357    ringbuffer_size_frames += 1; // to ensure that we can fit it all in there 
    13831358 
    13841359    debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state)); 
     
    13871362    switch(m_state) { 
    13881363        case ePS_Created: 
    1389             assert(m_data_buffer); 
    1390  
    13911364            // prepare the framerate estimate 
    13921365            ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_StreamProcessorManager.getNominalRate()); 
     
    13941367            m_local_node_id= m_1394service.getLocalNodeId() & 0x3f; 
    13951368            m_correct_last_timestamp = false; 
    1396  
     1369         
    13971370            debugOutput(DEBUG_LEVEL_VERBOSE, "Initializing remote ticks/frame to %f\n", ticks_per_frame); 
    1398  
     1371         
    13991372            // initialize internal buffer 
    14001373            result &= m_data_buffer->setBufferSize(ringbuffer_size_frames); 
    1401  
     1374         
    14021375            result &= m_data_buffer->setEventSize( getEventSize() ); 
    14031376            result &= m_data_buffer->setEventsPerFrame( getEventsPerFrame() ); 
     
    14081381            } 
    14091382            result &= m_data_buffer->setNominalRate(ticks_per_frame); 
    1410             result &= m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND); 
     1383            result &= m_data_buffer->setWrapValue(128L * TICKS_PER_SECOND); 
    14111384            result &= m_data_buffer->setBandwidth(STREAMPROCESSOR_DLL_FAST_BW_HZ / (double)TICKS_PER_SECOND); 
    14121385            result &= m_data_buffer->prepare(); // FIXME: the name 
     
    14141387            debugOutput(DEBUG_LEVEL_VERBOSE, "DLL info: nominal tpf: %f, update period: %d, bandwidth: %e 1/ticks (%e Hz)\n",  
    14151388                        m_data_buffer->getNominalRate(), m_data_buffer->getUpdatePeriod(), m_data_buffer->getBandwidth(), m_data_buffer->getBandwidth() * TICKS_PER_SECOND); 
    1416  
    14171389            break; 
    14181390        case ePS_DryRunning: 
     
    14271399    } 
    14281400 
    1429     result &= m_data_buffer->clearBuffer(); // FIXME: don't like the reset() name 
     1401    // clear all data 
     1402    result &= m_data_buffer->clearBuffer(); 
    14301403    // make the buffer transparent 
    14311404    m_data_buffer->setTransparent(true); 
     
    15441517{ 
    15451518    debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state)); 
    1546     unsigned int ringbuffer_size_frames; 
     1519 
     1520    unsigned int ringbuffer_size_frames = m_StreamProcessorManager.getNbBuffers() * m_StreamProcessorManager.getPeriodSize(); 
     1521    ringbuffer_size_frames += m_extra_buffer_frames; 
     1522    ringbuffer_size_frames += 1; // to ensure that we can fit it all in there 
     1523 
    15471524    switch(m_state) { 
    15481525        case ePS_DryRunning: 
     
    15511528            // be picked up by the packet iterator 
    15521529 
    1553             if(!m_data_buffer->clearBuffer()) { 
    1554                 debugError("Could not reset data buffer\n"); 
     1530            // clear the buffer / resize it to the most recent 
     1531            // size setting 
     1532            if(!m_data_buffer->resizeBuffer(ringbuffer_size_frames)) { 
     1533                debugError("Could not resize data buffer\n"); 
    15551534                return false; 
    15561535            } 
     1536 
    15571537            if (getType() == ePT_Transmit) { 
    15581538                ringbuffer_size_frames = m_StreamProcessorManager.getNbBuffers() * m_StreamProcessorManager.getPeriodSize(); 
    1559  
    1560                 // add sync delay 
    1561                 int syncdelay_in_frames = m_StreamProcessorManager.getSyncSource().getSyncDelayFrames(); 
    1562                 ringbuffer_size_frames += syncdelay_in_frames; 
    1563  
    1564                 debugOutput(DEBUG_LEVEL_VERBOSE, "Prefill transmit SP %p with %u frames (sync_delay_frames = %d)\n", 
    1565                             this, ringbuffer_size_frames, syncdelay_in_frames); 
     1539                ringbuffer_size_frames += m_extra_buffer_frames; 
     1540 
     1541                debugOutput(DEBUG_LEVEL_VERBOSE, "Prefill transmit SP %p with %u frames (xmit prebuffer = %d)\n", 
     1542                            this, ringbuffer_size_frames, m_extra_buffer_frames); 
    15661543                // prefill the buffer 
    15671544                if(!transferSilence(ringbuffer_size_frames)) { 
     
    19431920                                          24576000.0/m_StreamProcessorManager.getSyncSource().m_data_buffer->getRate(), 
    19441921                                          24576000.0/m_data_buffer->getRate()); 
    1945     float d = getSyncDelay(); 
    1946     debugOutputShort(DEBUG_LEVEL_NORMAL, "  Sync delay             : %f ticks (%f frames, %f cy)\n", 
    1947                                          d, d/getTicksPerFrame(), 
    1948                                          d/((float)TICKS_PER_CYCLE)); 
    19491922    #endif 
    19501923    m_data_buffer->dumpInfo(); 
  • branches/libffado-2.0/src/libstreaming/generic/StreamProcessor.h

    r1530 r1536  
    297297//--- data buffering and accounting 
    298298public: 
    299     void getBufferHeadTimestamp ( ffado_timestamp_t *ts, signed int *fc ) 
    300         {m_data_buffer->getBufferHeadTimestamp(ts, fc);}; 
    301     void getBufferTailTimestamp ( ffado_timestamp_t *ts, signed int *fc ) 
    302         {m_data_buffer->getBufferTailTimestamp(ts, fc);}; 
    303  
    304     void setBufferTailTimestamp ( ffado_timestamp_t new_timestamp ) 
    305         {m_data_buffer->setBufferTailTimestamp(new_timestamp);}; 
    306     void setBufferHeadTimestamp ( ffado_timestamp_t new_timestamp ) 
    307         {m_data_buffer->setBufferHeadTimestamp(new_timestamp);}; 
     299    void getBufferHeadTimestamp ( ffado_timestamp_t *ts, signed int *fc ); 
     300    void getBufferTailTimestamp ( ffado_timestamp_t *ts, signed int *fc ); 
     301 
     302    void setBufferTailTimestamp ( ffado_timestamp_t new_timestamp ); 
     303    void setBufferHeadTimestamp ( ffado_timestamp_t new_timestamp ); 
    308304protected: 
    309305    Util::TimestampedBuffer *m_data_buffer; 
     
    331327 
    332328        /** 
    333          * \brief return the time until the next period boundary should be signaled (in microseconds) 
    334          * 
    335          * Return the time until the next period boundary signal. If this StreamProcessor 
    336          * is the current synchronization source, this function is called to 
    337          * determine when a buffer transfer can be made. When this value is 
    338          * smaller than 0, a period boundary is assumed to be crossed, hence a 
    339          * transfer can be made. 
    340          * 
    341          * \return the time in usecs 
    342          */ 
    343         int64_t getTimeUntilNextPeriodSignalUsecs(); 
    344         /** 
    345          * \brief return the time of the next period boundary (in microseconds) 
    346          * 
    347          * Returns the time of the next period boundary, in microseconds. The 
    348          * goal of this function is to determine the exact point of the period 
     329         * \brief return the time of the next period boundary (in internal units) 
     330         * 
     331         * Returns the time of the next period boundary, in internal units, i.e. 
     332         * in ticks of the 1394 clock of the bus the device is attached to. 
     333         * The goal of this function is to determine the exact point of the period 
    349334         * boundary. This is assumed to be the point at which the buffer transfer should 
    350335         * take place, meaning that it can be used as a reference timestamp for transmitting 
    351336         * StreamProcessors 
    352337         * 
    353          * \return the time in usecs 
    354          */ 
    355         uint64_t getTimeAtPeriodUsecs(); 
    356  
    357         /** 
    358          * \brief return the time of the next period boundary (in internal units) 
    359          * 
    360          * The same as getTimeAtPeriodUsecs() but in internal units. 
    361          * 
    362338         * @return the time in internal units 
    363339         */ 
    364340        uint64_t getTimeAtPeriod(); 
    365341 
    366         uint64_t getTimeNow(); // FIXME: should disappear 
    367  
    368  
    369         /** 
    370          * Returns the sync delay. This is the time a syncsource 
    371          * delays a period signal, e.g. to cope with buffering. 
    372          * @return the sync delay (in ticks) 
    373          */ 
    374         unsigned int getSyncDelay(); 
    375         unsigned int getSyncDelayFrames(); 
    376         /** 
    377          * sets the sync delay 
    378          *  
    379          * note: will be rounded to an integer number of packets 
    380          *  
    381          * @param d sync delay 
    382          */ 
    383         void setSyncDelay(unsigned int ticks); 
     342        /** 
     343         * For RECEIVE: 
     344         * this is the extra amount of space in the receive buffer 
     345         * 
     346         * For XMIT: 
     347         * Sets the number of frames that should be prebuffered 
     348         * into the ISO transmit buffers. A higher number here means 
     349         * more reliable operation. It also means higher latency 
     350         * 
     351         * @param frames  
     352         */ 
     353        void setExtraBufferFrames(unsigned int frames); 
     354        unsigned int getExtraBufferFrames(); 
    384355 
    385356        /** 
     
    452423        float m_ticks_per_frame; 
    453424        float m_dll_bandwidth_hz; 
    454         unsigned int m_sync_delay_frames; 
     425        unsigned int m_extra_buffer_frames; 
    455426    private: 
    456427        bool m_in_xrun; 
  • branches/libffado-2.0/src/libstreaming/StreamProcessorManager.cpp

    r1530 r1536  
    5252    , m_nb_buffers( 0 ) 
    5353    , m_period( 0 ) 
     54    , m_sync_delay( 0 ) 
    5455    , m_audio_datatype( eADT_Float ) 
    5556    , m_nominal_framerate ( 0 ) 
     
    7677    , m_nb_buffers(nb_buffers) 
    7778    , m_period(period) 
     79    , m_sync_delay( 0 ) 
    7880    , m_audio_datatype( eADT_Float ) 
    7981    , m_nominal_framerate ( framerate ) 
     
    471473    // get the options 
    472474    int signal_delay_ticks = STREAMPROCESSORMANAGER_SIGNAL_DELAY_TICKS; 
     475    int xmit_prebuffer_frames = STREAMPROCESSORMANAGER_XMIT_PREBUFFER_FRAMES; 
    473476    int sync_wait_time_msec = STREAMPROCESSORMANAGER_SYNC_WAIT_TIME_MSEC; 
    474477    int cycles_for_startup = STREAMPROCESSORMANAGER_CYCLES_FOR_STARTUP; 
     
    477480    Util::Configuration &config = m_parent.getConfiguration(); 
    478481    config.getValueForSetting("streaming.spm.signal_delay_ticks", signal_delay_ticks); 
     482    config.getValueForSetting("streaming.spm.xmit_prebuffer_frames", xmit_prebuffer_frames); 
    479483    config.getValueForSetting("streaming.spm.sync_wait_time_msec", sync_wait_time_msec); 
    480484    config.getValueForSetting("streaming.spm.cycles_for_startup", cycles_for_startup); 
     
    513517    // at which the buffer is transfer()'ed. This makes things somewhat 
    514518    // more robust. 
    515     max_of_min_delay += signal_delay_ticks; 
    516  
    517     // Note that the equivalent number of frames is added to the  
    518     // transmit buffer to ensure that it keeps a good buffer fill, no matter 
    519     // what the sync delay is. 
    520     m_SyncSource->setSyncDelay(max_of_min_delay); 
    521     unsigned int syncdelay = m_SyncSource->getSyncDelay(); 
    522     debugOutput( DEBUG_LEVEL_VERBOSE, " sync delay = %d => %d ticks (%03us %04uc %04ut)...\n",  
    523         max_of_min_delay, syncdelay, 
    524         (unsigned int)TICKS_TO_SECS(syncdelay), 
    525         (unsigned int)TICKS_TO_CYCLES(syncdelay), 
    526         (unsigned int)TICKS_TO_OFFSET(syncdelay)); 
     519    m_sync_delay = max_of_min_delay + signal_delay_ticks; 
    527520 
    528521    //STEP X: when we implement such a function, we can wait for a signal from the devices that they 
     
    539532    nb_sync_runs /= getPeriodSize(); 
    540533 
    541     int64_t time_till_next_period; 
    542534    while(nb_sync_runs--) { // or while not sync-ed? 
    543535        // check if we were woken up too soon 
    544         time_till_next_period = m_SyncSource->getTimeUntilNextPeriodSignalUsecs(); 
    545         debugOutput( DEBUG_LEVEL_VERBOSE, "waiting for %d usecs...\n", time_till_next_period); 
    546         if(time_till_next_period > 0) { 
    547             // wait for the period 
    548             SleepRelativeUsec(time_till_next_period); 
    549         } 
     536        uint64_t ticks_at_period = m_SyncSource->getTimeAtPeriod(); 
     537        uint64_t ticks_at_period_margin = ticks_at_period + m_sync_delay; 
     538        uint64_t pred_system_time_at_xfer = m_SyncSource->getParent().get1394Service().getSystemTimeForCycleTimerTicks(ticks_at_period_margin); 
     539     
     540        #ifdef DEBUG 
     541        int64_t now = Util::SystemTimeSource::getCurrentTime(); 
     542        debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "CTR  pred: %lld, syncdelay: %lld, diff: %lld\n", ticks_at_period, ticks_at_period_margin, ticks_at_period_margin-ticks_at_period ); 
     543        debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "PREWAIT  pred: %lld, now: %lld, wait: %lld\n", pred_system_time_at_xfer, now, pred_system_time_at_xfer-now ); 
     544        #endif 
     545     
     546        // wait until it's time to transfer 
     547        Util::SystemTimeSource::SleepUsecAbsolute(pred_system_time_at_xfer); 
     548     
     549        #ifdef DEBUG 
     550        now = Util::SystemTimeSource::getCurrentTime(); 
     551        debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "POSTWAIT pred: %lld, now: %lld, excess: %lld\n", pred_system_time_at_xfer, now, now-pred_system_time_at_xfer ); 
     552        #endif 
    550553    } 
    551554 
     
    562565    } 
    563566    debugOutput( DEBUG_LEVEL_VERBOSE, " sync source frame rate: %f fps (%f tpf)\n", syncrate, tpf); 
    564  
    565     m_SyncSource->setSyncDelay(max_of_min_delay); 
    566     syncdelay = m_SyncSource->getSyncDelay(); 
    567     debugOutput( DEBUG_LEVEL_VERBOSE, " updated sync delay = %d => %d ticks (%f frames) (%03us %04uc %04ut)...\n",  
    568         max_of_min_delay, syncdelay, syncdelay/tpf, 
    569         (unsigned int)TICKS_TO_SECS(syncdelay), 
    570         (unsigned int)TICKS_TO_CYCLES(syncdelay), 
    571         (unsigned int)TICKS_TO_OFFSET(syncdelay)); 
    572567 
    573568    // we now should have decent sync info on the sync source 
     
    619614        (unsigned int)TICKS_TO_OFFSET(time_to_start_recv)); 
    620615 
     616    // print the sync delay 
     617    int sync_delay_frames = (int)((float)m_sync_delay / m_SyncSource->getTicksPerFrame()); 
     618    debugOutput( DEBUG_LEVEL_VERBOSE, " sync delay: %d = %d + %d ticks (%03us %04uc %04ut) [%d frames]...\n",  
     619        m_sync_delay, max_of_min_delay, signal_delay_ticks, 
     620        (unsigned int)TICKS_TO_SECS(m_sync_delay), 
     621        (unsigned int)TICKS_TO_CYCLES(m_sync_delay), 
     622        (unsigned int)TICKS_TO_OFFSET(m_sync_delay), 
     623        sync_delay_frames); 
     624 
     625    // check if this can even work. 
     626    // the worst case point where we can receive a period is at 1 period + sync delay 
     627    // this means that the number of frames in the xmit buffer has to be at least 
     628    // 1 period + sync delay 
     629    if(xmit_prebuffer_frames + m_period * m_nb_buffers < m_period + sync_delay_frames) { 
     630        debugWarning("The amount of transmit buffer frames (%d) is too small (< %d). " 
     631                     "This will most likely cause xruns.\n", 
     632                     xmit_prebuffer_frames + m_period * m_nb_buffers, 
     633                     m_period + sync_delay_frames); 
     634    } 
     635 
    621636    // at this point the buffer head timestamp of the transmit buffers can be set 
    622637    // this is the presentation time of the first sample in the buffer 
     
    624639          it != m_TransmitProcessors.end(); 
    625640          ++it ) { 
     641        // set the number of prebuffer frames 
     642        (*it)->setExtraBufferFrames(xmit_prebuffer_frames); 
     643 
     644        // set the TSP of the first sample in the buffer 
    626645        (*it)->setBufferHeadTimestamp(time_of_first_sample); 
    627646        ffado_timestamp_t ts; 
     
    630649        debugOutput( DEBUG_LEVEL_VERBOSE, " transmit buffer tail %010lld => head TS %010lld, fc=%d...\n", 
    631650                    time_of_first_sample, (uint64_t)ts, fc); 
     651    } 
     652 
     653    // the receive processors can be delayed by sync_delay ticks 
     654    // this means that in the worst case we have to be able to accomodate 
     655    // an extra sync_delay ticks worth of frames in the receive SP buffer 
     656    // the sync delay should be rounded to an integer amount of max_packet_size 
     657    int tmp = sync_delay_frames / max_packet_size_frames; 
     658    tmp = tmp + 1; 
     659    sync_delay_frames = tmp * max_packet_size_frames; 
     660    if (sync_delay_frames < 1024) sync_delay_frames = 1024; //HACK 
     661 
     662    for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
     663          it != m_ReceiveProcessors.end(); 
     664          ++it ) { 
     665        // set the number of extra buffer frames 
     666        (*it)->setExtraBufferFrames(sync_delay_frames); 
    632667    } 
    633668 
     
    698733                m_time_of_transfer, rate); 
    699734 
    700     int64_t delay_in_ticks = (int64_t)(((float)((m_nb_buffers-1) * m_period)) * rate); 
    701     // also add the sync delay 
    702     delay_in_ticks = addTicks(delay_in_ticks, m_SyncSource->getSyncDelay()); 
    703  
     735    // FIXME: ideally we'd want the SP itself to account for the xmit_prebuffer_frames 
     736    // but that would also require to use a different approach to setting the initial TSP's 
     737    int64_t delay_in_ticks = (int64_t)(((float)((m_nb_buffers-1) * m_period + xmit_prebuffer_frames)) * rate); 
    704738 
    705739    // then use this information to initialize the xmit handlers 
     
    708742    //  to the period transfer time instant plus what's nb_buffers - 1 
    709743    //  in ticks. This due to the fact that we (should) have received one period 
    710     //  worth of ticks at t=m_time_of_transfer 
     744    //  worth of ticks at t = m_time_of_transfer 
    711745    //  hence one period of frames should also have been transmitted, which means 
    712746    //  that there should be (nb_buffers - 1) * periodsize of frames in the xmit buffer 
     747    //  there are also xmit_prebuffer_frames frames extra present in the buffer 
    713748    //  that allows us to calculate the tail timestamp for the buffer. 
    714749 
     
    10471082                        m_SyncSource->getBufferFill()); 
    10481083    uint64_t ticks_at_period = m_SyncSource->getTimeAtPeriod(); 
    1049     uint64_t ticks_at_period_margin = ticks_at_period + m_SyncSource->getSyncDelay()
     1084    uint64_t ticks_at_period_margin = ticks_at_period + m_sync_delay
    10501085    uint64_t pred_system_time_at_xfer = m_SyncSource->getParent().get1394Service().getSystemTimeForCycleTimerTicks(ticks_at_period_margin); 
    10511086 
    10521087    #ifdef DEBUG 
    10531088    int64_t now = Util::SystemTimeSource::getCurrentTime(); 
    1054     debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "pred: %lld, now: %lld, wait: %lld\n", pred_system_time_at_xfer, now, pred_system_time_at_xfer-now ); 
     1089    debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "CTR  pred: %lld, syncdelay: %lld, diff: %lld\n", ticks_at_period, ticks_at_period_margin, ticks_at_period_margin-ticks_at_period ); 
     1090    debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "PREWAIT  pred: %lld, now: %lld, wait: %lld\n", pred_system_time_at_xfer, now, pred_system_time_at_xfer-now ); 
    10551091    #endif 
    10561092 
     
    10601096    #ifdef DEBUG 
    10611097    now = Util::SystemTimeSource::getCurrentTime(); 
    1062     debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "pred: %lld now: %lld, excess: %lld\n", pred_system_time_at_xfer, now, now-pred_system_time_at_xfer ); 
     1098    debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "POSTWAIT pred: %lld, now: %lld, excess: %lld\n", pred_system_time_at_xfer, now, now-pred_system_time_at_xfer ); 
    10631099    #endif 
    10641100 
    10651101    // the period should be ready now 
     1102    #ifdef DEBUG 
     1103    int rcv_fills[10]; 
     1104    int xmt_fills[10]; 
     1105    int i; 
     1106    i=0; 
     1107    for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
     1108        it != m_ReceiveProcessors.end(); 
     1109        ++it ) { 
     1110        rcv_fills[i] = (*it)->getBufferFill(); 
     1111        debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "RECV SP %p bufferfill: %05d\n", *it, rcv_fills[i]); 
     1112        i++; 
     1113    } 
     1114    i=0; 
     1115    for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
     1116        it != m_TransmitProcessors.end(); 
     1117        ++it ) { 
     1118        xmt_fills[i] = (*it)->getBufferFill(); 
     1119        debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "XMIT SP %p bufferfill: %05d\n", *it, xmt_fills[i]); 
     1120        i++; 
     1121    } 
     1122    for(i=0;i<1;i++) { 
     1123        debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "SP %02d RECV: %05d [%05d] XMIT: %05d [%05d] DIFF: %05d\n", i, 
     1124                    rcv_fills[i], rcv_fills[i] - m_period, 
     1125                    xmt_fills[i], xmt_fills[i] - m_period, 
     1126                    rcv_fills[i] - xmt_fills[i]); 
     1127    } 
     1128    #endif 
    10661129 
    10671130    #if STREAMPROCESSORMANAGER_ALLOW_DELAYED_PERIOD_SIGNAL 
     
    11731236                        m_nbperiods, m_time_of_transfer); 
    11741237 
    1175     // this is to notify the client of the delay that we introduced by waiting 
    1176     m_delayed_usecs = - m_SyncSource->getTimeUntilNextPeriodSignalUsecs(); 
    1177     debugOutputExtreme(DEBUG_LEVEL_VERBOSE, 
    1178                         "delayed for %d usecs...\n", 
    1179                         m_delayed_usecs); 
    1180  
    1181 #ifdef DEBUG 
     1238    #ifdef DEBUG 
    11821239    int rcv_bf=0, xmt_bf=0; 
    11831240    for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
     
    12241281        } 
    12251282    } 
    1226 #endif 
     1283    #endif 
    12271284    m_nbperiods++; 
     1285 
     1286    // this is to notify the client of the delay that we introduced by waiting 
     1287    pred_system_time_at_xfer = m_SyncSource->getParent().get1394Service().getSystemTimeForCycleTimerTicks(m_time_of_transfer); 
     1288 
     1289    m_delayed_usecs = Util::SystemTimeSource::getCurrentTime() - pred_system_time_at_xfer; 
     1290    debugOutputExtreme(DEBUG_LEVEL_VERBOSE, 
     1291                        "delayed for %d usecs...\n", 
     1292                        m_delayed_usecs); 
     1293 
    12281294    // now we can signal the client that we are (should be) ready 
    12291295    return !xrun_occurred; 
     
    12791345        //        1394 time 
    12801346        float rate = m_SyncSource->getTicksPerFrame(); 
    1281         int64_t one_ringbuffer_in_ticks=(int64_t)(((float)((m_nb_buffers * m_period))) * rate); 
    1282  
    1283         // the data we are putting into the buffer is intended to be transmitted 
    1284         // one ringbuffer size after it has been received 
    1285  
    1286         // we also add one syncdelay as a safety margin, since that's the amount of time we can get 
    1287         // postponed. 
    1288         int syncdelay = m_SyncSource->getSyncDelay(); 
    1289         int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks + syncdelay); 
    12901347 
    12911348        for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
    12921349                it != m_TransmitProcessors.end(); 
    12931350                ++it ) { 
    1294             // FIXME: in the SPM it would be nice to have system time instead of 
    1295             //        1394 time 
     1351            // this is the delay in frames between the point where a frame is received and 
     1352            // when it is transmitted again 
     1353            unsigned int one_ringbuffer_in_frames = m_nb_buffers * m_period + (*it)->getExtraBufferFrames(); 
     1354            int64_t one_ringbuffer_in_ticks = (int64_t)(((float)one_ringbuffer_in_frames) * rate); 
     1355     
     1356            // the data we are putting into the buffer is intended to be transmitted 
     1357            // one ringbuffer size after it has been received 
     1358            int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks); 
     1359 
    12961360            if(!(*it)->putFrames(m_period, transmit_timestamp)) { 
    12971361                debugWarning("could not putFrames(%u,%llu) to stream processor (%p)\n", 
     
    13591423        //        1394 time 
    13601424        float rate = m_SyncSource->getTicksPerFrame(); 
    1361         int64_t one_ringbuffer_in_ticks=(int64_t)(((float)(m_nb_buffers * m_period)) * rate); 
    1362  
    1363         // the data we are putting into the buffer is intended to be transmitted 
    1364         // one ringbuffer size after it has been received 
    1365         // we also add one syncdelay as a safety margin, since that's the amount of time we can get 
    1366         // postponed. 
    1367         int syncdelay = m_SyncSource->getSyncDelay(); 
    1368         int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks + syncdelay); 
    13691425 
    13701426        for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
    13711427                it != m_TransmitProcessors.end(); 
    13721428                ++it ) { 
    1373             // FIXME: in the SPM it would be nice to have system time instead of 
    1374             //        1394 time 
     1429            // this is the delay in frames between the point where a frame is received and 
     1430            // when it is transmitted again 
     1431            unsigned int one_ringbuffer_in_frames = m_nb_buffers * m_period + (*it)->getExtraBufferFrames(); 
     1432            int64_t one_ringbuffer_in_ticks = (int64_t)(((float)one_ringbuffer_in_frames) * rate); 
     1433     
     1434            // the data we are putting into the buffer is intended to be transmitted 
     1435            // one ringbuffer size after it has been received 
     1436            int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks); 
     1437 
    13751438            if(!(*it)->putSilenceFrames(m_period, transmit_timestamp)) { 
    13761439                debugWarning("could not putSilenceFrames(%u,%llu) to stream processor (%p)\n", 
  • branches/libffado-2.0/src/libstreaming/StreamProcessorManager.h

    r1528 r1536  
    190190    unsigned int m_nb_buffers; 
    191191    unsigned int m_period; 
     192    unsigned int m_sync_delay; 
    192193    enum eADT_AudioDataType m_audio_datatype; 
    193194    unsigned int m_nominal_framerate; 
  • branches/libffado-2.0/src/libutil/TimestampedBuffer.cpp

    r1530 r1536  
    383383    m_current_rate = m_nominal_rate; 
    384384 
    385     if( !(m_event_buffer=ffado_ringbuffer_create( 
    386             (m_events_per_frame * m_buffer_size) * m_event_size))) { 
    387         debugFatal("Could not allocate memory event ringbuffer\n"); 
     385    if( !resizeBuffer(m_buffer_size) ) { 
     386        debugError("Failed to allocate the event buffer\n"); 
    388387        return false; 
    389388    } 
     
    408407    m_buffer_tail_timestamp = TIMESTAMP_MAX + 1.0; 
    409408    m_buffer_next_tail_timestamp = TIMESTAMP_MAX + 1.0; 
     409 
     410    return true; 
     411} 
     412 
     413/** 
     414 * Resizes the timestamped buffer 
     415 * @return true if successful, false if not 
     416 */ 
     417bool 
     418TimestampedBuffer::resizeBuffer(unsigned int new_size) 
     419{ 
     420    assert(new_size); 
     421    assert(m_events_per_frame); 
     422    assert(m_event_size); 
     423 
     424    // if present, free the previous buffer 
     425    if(m_event_buffer) { 
     426        ffado_ringbuffer_free(m_event_buffer); 
     427    } 
     428    // allocate a new one 
     429    if( !(m_event_buffer = ffado_ringbuffer_create( 
     430            (m_events_per_frame * new_size) * m_event_size))) { 
     431        debugFatal("Could not allocate memory event ringbuffer\n"); 
     432 
     433        return false; 
     434    } 
     435    resetFrameCounter(); 
     436 
     437    m_current_rate = m_nominal_rate; 
     438    m_dll_e2 = m_current_rate * (float)m_update_period; 
     439 
     440    m_buffer_size = new_size; 
    410441 
    411442    return true; 
  • branches/libffado-2.0/src/libutil/TimestampedBuffer.h

    r1530 r1536  
    152152        void dumpInfo(); 
    153153        void setVerboseLevel ( int l ) {setDebugLevel ( l );}; 
     154 
     155        bool resizeBuffer(unsigned int size); 
    154156 
    155157    private: