Changeset 1001

Show
Ignore:
Timestamp:
04/19/08 05:18:01 (16 years ago)
Author:
ppalmers
Message:

Improve streaming startup for better initial timestamps and locking.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp

    r979 r1001  
    9595    // to be output by the device 
    9696    presentation_time = ( uint64_t ) ts_head_tmp; 
    97     m_last_timestamp = presentation_time; 
    9897 
    9998    // now we calculate the time when we have to transmit the sample block 
     
    211210//                 // we are not that late and can still try to transmit the packet 
    212211//                 m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp); 
     212//                 m_last_timestamp = presentation_time; 
    213213//                 return (fc < (signed)(2*m_syt_interval) ? eCRV_Defer : eCRV_Packet); 
    214214//             } 
     
    222222            // it's time send the packet 
    223223            m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp); 
     224            m_last_timestamp = presentation_time; 
     225 
     226            // FIXME: this should not be multiplied by 2 
    224227            return (fc < (signed)(2*m_syt_interval) ? eCRV_Defer : eCRV_Packet); 
    225228        } 
  • trunk/libffado/src/libstreaming/generic/StreamProcessor.cpp

    r1000 r1001  
    254254} 
    255255 
     256void 
     257StreamProcessor::setTicksPerFrame(float tpf) 
     258{ 
     259    assert(m_data_buffer != NULL); 
     260    m_data_buffer->setRate(tpf); 
     261} 
     262 
    256263bool 
    257264StreamProcessor::canClientTransferFrames(unsigned int nbframes) 
     
    306313            m_dropped += dropped_cycles; 
    307314            m_last_cycle = cycle; 
     315            m_Parent.showDevice(); 
     316//             flushDebugOutput(); 
     317//             assert(0); 
    308318        } 
    309319    } 
     
    384394    if (result == eCRV_OK) { 
    385395        #ifdef DEBUG 
    386         int ticks_per_packet = getTicksPerFrame() * getNominalFramesPerPacket(); 
     396        int ticks_per_packet = (int)(getTicksPerFrame() * getNominalFramesPerPacket()); 
    387397        int diff=diffTicks(m_last_timestamp, m_last_timestamp2); 
    388398        // display message if the difference between two successive tick 
     
    390400        // so 50 ticks = 10%, which is a rather large jitter value. 
    391401        if(diff-ticks_per_packet > 50 || diff-ticks_per_packet < -50) { 
    392             debugOutput(DEBUG_LEVEL_VERBOSE, "rather large TSP difference TS=%011llu => TS=%011llu (%d, nom %d)\n", 
    393                                              m_last_timestamp2, m_last_timestamp, diff, ticks_per_packet); 
    394         } 
     402            debugOutput(DEBUG_LEVEL_VERBOSE, 
     403                        "cy %04u rather large TSP difference TS=%011llu => TS=%011llu (%d, nom %d)\n", 
     404                        cycle, m_last_timestamp2, m_last_timestamp, diff, ticks_per_packet); 
     405        } 
     406        debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, 
     407                           "%04u %011llu %011llu %d %d\n", 
     408                           cycle, m_last_timestamp2, m_last_timestamp,  
     409                           diff, ticks_per_packet); 
    395410        #endif 
    396411 
     
    496511 
    497512    unsigned int ctr; 
     513    uint64_t prev_timestamp; 
    498514    int now_cycles; 
    499515    int cycle_diff; 
     
    594610 
    595611    // store the previous timestamp 
    596     m_last_timestamp2 = m_last_timestamp; 
    597  
     612    // keep the old value here, update m_last_timestamp2 only when 
     613    // a valid packet will be sent 
     614    prev_timestamp = m_last_timestamp; 
     615     
    598616    // NOTE: synchronized switching is restricted to a 0.5 sec span (4000 cycles) 
    599617    //       it happens on the first 'good' cycle for the wait condition 
     
    624642            generateSilentPacketData(data, length, tag, sy, cycle, dropped_cycles, max_length); 
    625643            return RAW1394_ISO_OK; 
     644        // FIXME: PP: I think this should be possible too 
     645        //} else if (result == eCRV_EmptyPacket) { 
     646        //    goto send_empty_packet; 
    626647        } else { 
    627648            debugError("Invalid return value: %d\n", result); 
     
    672693            m_last_good_cycle = cycle; 
    673694            m_last_dropped = dropped_cycles; 
     695 
     696            // valid packet timestamp 
     697            m_last_timestamp2 = prev_timestamp; 
    674698 
    675699            // check whether a state change has been requested 
     
    701725                goto send_empty_packet; 
    702726            } 
     727            #ifdef DEBUG 
     728            int ticks_per_packet = (int)(getTicksPerFrame() * getNominalFramesPerPacket()); 
     729            int diff=diffTicks(m_last_timestamp, m_last_timestamp2); 
     730            // display message if the difference between two successive tick 
     731            // values is more than 50 ticks. 1 sample at 48k is 512 ticks 
     732            // so 50 ticks = 10%, which is a rather large jitter value. 
     733            if(diff-ticks_per_packet > 50 || diff-ticks_per_packet < -50) { 
     734                debugOutput(DEBUG_LEVEL_VERBOSE, 
     735                            "cy %04d, rather large TSP difference TS=%011llu => TS=%011llu (%d, nom %d)\n", 
     736                            cycle, m_last_timestamp2, m_last_timestamp, diff, ticks_per_packet); 
     737            } 
     738            debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, 
     739                               "%04d %011llu %011llu %d %d\n", 
     740                               cycle, m_last_timestamp2, m_last_timestamp, diff, ticks_per_packet); 
     741            #endif 
     742 
    703743            // skip queueing packets if we detect that there are not enough frames 
    704744            // available 
    705             if(result2 == eCRV_Defer || result == eCRV_Defer) 
     745            if(result2 == eCRV_Defer || result == eCRV_Defer) { 
    706746                return RAW1394_ISO_DEFER; 
    707             else 
     747            } else { 
    708748                return RAW1394_ISO_OK; 
     749            } 
    709750        } else if (result == eCRV_XRun) { // pick up the possible xruns 
    710751            debugWarning("generatePacketHeader xrun\n"); 
  • trunk/libffado/src/libstreaming/generic/StreamProcessor.h

    r967 r1001  
    314314    int m_last_good_cycle; /// FIXME:debug 
    315315    uint64_t m_last_timestamp; /// last timestamp (in ticks) 
     316private: 
    316317    uint64_t m_last_timestamp2; /// last timestamp (in ticks) 
     318protected: 
    317319    bool m_correct_last_timestamp; 
    318320    uint64_t m_last_timestamp_at_period_ticks; // FIXME: still used? 
     
    420422 
    421423        float getTicksPerFrame(); 
     424        void setTicksPerFrame(float tpf); 
    422425 
    423426        int getLastCycle() {return m_last_cycle;}; 
     
    466469         */ 
    467470        virtual unsigned int getNominalPacketsNeeded(unsigned int nframes); 
    468  
    469         /** 
    470          * @brief returns the actual frame rate as calculated by the SP's DLL 
    471          * @return the actual frame rate as detected by the DLL 
    472          */ 
    473         float getActualRate() 
    474             {return m_data_buffer->getRate();}; 
    475471 
    476472    protected: 
  • trunk/libffado/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp

    r991 r1001  
    128128    // to be output by the device 
    129129    presentation_time = ( uint64_t ) ts_head_tmp; 
    130     m_last_timestamp = presentation_time; 
    131130 
    132131    // now we calculate the time when we have to transmit the sample block 
     
    224223                // we are not that late and can still try to transmit the packet 
    225224                m_tx_dbc += fillDataPacketHeader((quadlet_t *)data, length, m_last_timestamp); 
     225                m_last_timestamp = presentation_time; 
    226226                if (m_tx_dbc > 0xff) 
    227227                    m_tx_dbc -= 0x100; 
     
    237237            // it's time send the packet 
    238238            m_tx_dbc += fillDataPacketHeader((quadlet_t *)data, length, m_last_timestamp); 
     239            m_last_timestamp = presentation_time; 
    239240            if (m_tx_dbc > 0xff) 
    240241                m_tx_dbc -= 0x100; 
     
    284285 
    285286    if (m_data_buffer->readFrames(n_events, (char *)(data + 8))) { 
    286         float ticks_per_frame = m_Parent.getDeviceManager().getStreamProcessorManager().getSyncSource().getActualRate(); 
     287        float ticks_per_frame = m_Parent.getDeviceManager().getStreamProcessorManager().getSyncSource().getTicksPerFrame(); 
    287288 
    288289#if TESTTONE 
     
    410411 
    411412    memset(quadlet, 0, n_events*m_event_size); 
    412     float ticks_per_frame = m_Parent.getDeviceManager().getStreamProcessorManager().getSyncSource().getActualRate(); 
     413    float ticks_per_frame = m_Parent.getDeviceManager().getStreamProcessorManager().getSyncSource().getTicksPerFrame(); 
    413414 
    414415    // Set up each frames's SPH. 
  • trunk/libffado/src/libstreaming/StreamProcessorManager.cpp

    r967 r1001  
    428428    } 
    429429 
    430     // STEP X: switch SP's over to the running state 
     430    // switch syncsource to running state 
     431    uint64_t time_to_start_sync; 
     432    // FIXME: this is most likely not going to work for transmit sync sources 
     433    // but those are unsupported in this version 
     434    if(m_SyncSource->getType() == StreamProcessor::ePT_Receive ) { 
     435        time_to_start_sync = time_to_start_recv; 
     436    } else {  
     437        time_to_start_sync = time_to_start_xmit; 
     438    } 
     439    if(!m_SyncSource->scheduleStartRunning(time_to_start_sync)) { 
     440        debugError("m_SyncSource->scheduleStartRunning(%11llu) failed\n", time_to_start_sync); 
     441        return false; 
     442    } 
     443 
     444    // STEP X: switch all non-syncsource SP's over to the running state 
    431445    for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
    432446          it != m_ReceiveProcessors.end(); 
    433447          ++it ) { 
    434         if(!(*it)->scheduleStartRunning(time_to_start_recv)) { 
    435             debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_recv); 
    436             return false; 
     448        if(*it != m_SyncSource) { 
     449            if(!(*it)->scheduleStartRunning(time_to_start_recv)) { 
     450                debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_recv); 
     451                return false; 
     452            } 
    437453        } 
    438454    } 
     
    440456          it != m_TransmitProcessors.end(); 
    441457          ++it ) { 
    442         if(!(*it)->scheduleStartRunning(time_to_start_xmit)) { 
    443             debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_xmit); 
    444             return false; 
     458        if(*it != m_SyncSource) { 
     459            if(!(*it)->scheduleStartRunning(time_to_start_xmit)) { 
     460                debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_xmit); 
     461                return false; 
     462            } 
    445463        } 
    446464    } 
    447465    // wait for the syncsource to start running. 
    448466    // that will block the waitForPeriod call until everyone has started (theoretically) 
     467    // note: the SP's are scheduled to start in STREAMPROCESSORMANAGER_CYCLES_FOR_STARTUP cycles, 
     468    // so a 20 times this value should be a good timeout 
    449469    int cnt = STREAMPROCESSORMANAGER_CYCLES_FOR_STARTUP * 20; // by then it should have started 
    450470    while (!m_SyncSource->isRunning() && cnt) { 
     
    457477    } 
    458478 
     479    // the sync source is running, we can now read a decent received timestamp from it 
     480    m_time_of_transfer = m_SyncSource->getTimeAtPeriod(); 
     481 
     482    // and a (still very rough) approximation of the rate 
     483    float rate = m_SyncSource->getTicksPerFrame(); 
     484    int64_t delay_in_ticks=(int64_t)(((float)((m_nb_buffers-1) * m_period)) * rate); 
     485    debugOutput( DEBUG_LEVEL_VERBOSE, "  initial time of transfer %010lld, rate %f...\n", 
     486                m_time_of_transfer, rate); 
     487 
     488    // then use this information to initialize the xmit handlers 
     489 
     490    //  we now set the buffer tail timestamp of the transmit buffer 
     491    //  to the period transfer time instant plus what's nb_buffers - 1 
     492    //  in ticks. This due to the fact that we (should) have received one period 
     493    //  worth of ticks at t=m_time_of_transfer 
     494    //  hence one period of frames should also have been transmitted, which means 
     495    //  that there should be (nb_buffers - 1) * periodsize of frames in the xmit buffer 
     496    //  that allows us to calculate the tail timestamp for the buffer. 
     497 
     498    int64_t transmit_tail_timestamp = addTicks(m_time_of_transfer, delay_in_ticks); 
     499 
     500    debugOutput( DEBUG_LEVEL_VERBOSE, "  preset transmit tail TS %010lld, rate %f...\n", 
     501                transmit_tail_timestamp, rate); 
     502 
     503    for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
     504        it != m_TransmitProcessors.end(); 
     505        ++it ) { 
     506        (*it)->setBufferTailTimestamp(transmit_tail_timestamp); 
     507        (*it)->setTicksPerFrame(rate); 
     508    } 
     509 
     510    // align the received streams to be phase aligned 
    459511    if(!alignReceivedStreams()) { 
    460512        debugError("Could not align streams...\n"); 
     
    506558            } 
    507559 
    508             // we now set the buffer tail timestamp of the transmit buffer 
    509             // to the period transfer time instant plus what's nb_buffers - 1 
    510             // in ticks. This due to the fact that we (should) have received one period 
    511             // worth of ticks at t=m_time_of_transfer 
    512             // hence one period of frames should also have been transmitted, which means 
    513             // that there should be (nb_buffers - 1) * periodsize of frames in the xmit buffer 
    514             // that allows us to calculate the tail timestamp for the buffer. 
    515             float rate = m_SyncSource->getTicksPerFrame(); 
    516             int64_t delay_in_ticks=(int64_t)(((float)((m_nb_buffers-1) * m_period)) * rate); 
    517             int64_t transmit_tail_timestamp = addTicks(m_time_of_transfer, delay_in_ticks); 
    518  
    519             for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
    520                   it != m_TransmitProcessors.end(); 
    521                   ++it ) { 
    522                 // m_time_of_transfer is set by waitForPeriod() 
    523                 (*it)->setBufferTailTimestamp(transmit_tail_timestamp); 
    524             } 
    525  
    526560            if(!transferSilence()) { 
    527561                debugError("Could not transfer silence\n"); 
     
    840874    static uint64_t m_time_of_transfer2 = m_time_of_transfer; 
    841875     
    842     int ticks_per_period = m_SyncSource->getTicksPerFrame() * m_period
     876    int ticks_per_period = (int)(m_SyncSource->getTicksPerFrame() * m_period)
    843877    int diff=diffTicks(m_time_of_transfer, m_time_of_transfer2); 
    844878    // display message if the difference between two successive tick 
     
    961995        //        1394 time 
    962996        float rate = m_SyncSource->getTicksPerFrame(); 
    963         int64_t one_ringbuffer_in_ticks=(int64_t)(((float)(m_nb_buffers * m_period)) * rate); 
     997        int64_t one_ringbuffer_in_ticks=(int64_t)(((float)((m_nb_buffers * m_period))) * rate); 
    964998 
    965999        // the data we are putting into the buffer is intended to be transmitted 
     
    9911025 */ 
    9921026bool StreamProcessorManager::transferSilence() { 
    993     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring silent period...\n"); 
     1027    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Transferring silent period...\n"); 
    9941028    bool retval=true; 
    9951029    retval &= transferSilence(StreamProcessor::ePT_Receive); 
  • trunk/libffado/src/libutil/TimestampedBuffer.cpp

    r918 r1001  
    147147 
    148148/** 
     149 * \brief presets the effective rate 
     150 * 
     151 * Presets the DLL such that the effective rate is as given 
     152 * @param rate rate (in timeunits/frame) 
     153 */ 
     154void TimestampedBuffer::setRate(float rate) { 
     155    // we take the current tail timestamp and update the head timestamp 
     156    // to ensure the rate is ok 
     157 
     158    ENTER_CRITICAL_SECTION; 
     159 
     160    m_dll_e2 = m_update_period * (double)rate; 
     161    m_buffer_next_tail_timestamp = (ffado_timestamp_t)((double)m_buffer_tail_timestamp + m_dll_e2); 
     162 
     163    EXIT_CRITICAL_SECTION; 
     164 
     165    debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, 
     166                       "for (%p) to "TIMESTAMP_FORMAT_SPEC" => "TIMESTAMP_FORMAT_SPEC", " 
     167                       "NTS="TIMESTAMP_FORMAT_SPEC", DLL2=%f, RATE=%f\n", 
     168                       this, new_timestamp, ts, m_buffer_next_tail_timestamp, m_dll_e2, getRate()); 
     169} 
     170 
     171/** 
    149172 * \brief calculate the effective rate 
    150173 * 
  • trunk/libffado/src/libutil/TimestampedBuffer.h

    r907 r1001  
    139139        float getNominalRate() {return m_nominal_rate;}; 
    140140        float getRate(); 
     141        void setRate(float rate); 
    141142 
    142143        bool setUpdatePeriod ( unsigned int t );