Show
Ignore:
Timestamp:
01/06/08 03:15:01 (16 years ago)
Author:
ppalmers
Message:

- AMDTP transmit port caching for better performance
- less debug output in critical path

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/api-cleanup/src/libstreaming/amdtp/AmdtpPortInfo.h

    r742 r815  
    6060 
    6161 
    62     int getLocation()     {return m_location;}; 
    63     int getPosition()     {return m_position;}; 
     62    unsigned int getLocation()     {return m_location;}; 
     63    unsigned int getPosition()     {return m_position;}; 
    6464    enum E_Formats getFormat()       {return m_format;}; 
    6565 
    6666protected: 
    67     int m_position; 
    68     int m_location; 
     67    unsigned int m_position; 
     68    unsigned int m_location; 
    6969    enum E_Formats m_format; 
    7070 
  • branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp

    r812 r815  
    3737#include <assert.h> 
    3838 
     39#define AMDTP_FLOAT_MULTIPLIER 2147483392.0 
     40 
    3941namespace Streaming 
    4042{ 
     
    4547        , m_dimension( dimension ) 
    4648        , m_dbc( 0 ) 
     49        , m_nb_audio_ports( 0 ) 
     50        , m_nb_midi_ports( 0 ) 
    4751{} 
    4852 
     
    388392        m_syt_interval ); 
    389393 
     394    if (!initPortCache()) { 
     395        debugError("Could not init port cache\n"); 
     396        return false; 
     397    } 
     398 
    390399    return true; 
    391400} 
     
    398407{ 
    399408    bool no_problem = true; 
    400  
    401     for ( PortVectorIterator it = m_Ports.begin(); 
    402           it != m_Ports.end(); 
    403           ++it ) 
    404     { 
    405         if ( (*it)->isDisabled() ) { continue; }; 
    406  
    407         //FIXME: make this into a static_cast when not DEBUG? 
    408         AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it ); 
    409         assert ( pinfo ); // this should not fail!! 
    410  
    411         switch( pinfo->getFormat() ) 
    412         { 
    413             case AmdtpPortInfo::E_MBLA: 
    414                 if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
    415                 { 
    416                     debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() ); 
    417                     no_problem = false; 
    418                 } 
    419                 break; 
    420             case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    421                 break; 
    422             case AmdtpPortInfo::E_Midi: 
    423                 if( encodePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
    424                 { 
    425                     debugWarning ( "Could not encode port %s to Midi events", (*it)->getName().c_str() ); 
    426                     no_problem = false; 
    427                 } 
    428                 break; 
    429             default: // ignore 
    430                 break; 
    431         } 
    432     } 
     409    updatePortCache(); 
     410 
     411    if(!encodeAudioPorts((quadlet_t *)data, offset, nevents)) { 
     412        debugError("Could not encode audio ports\n"); 
     413        return false; 
     414    } 
     415 
     416//     for ( PortVectorIterator it = m_Ports.begin(); 
     417//           it != m_Ports.end(); 
     418//           ++it ) 
     419//     { 
     420//         if ( (*it)->isDisabled() ) { continue; }; 
     421//  
     422//         //FIXME: make this into a static_cast when not DEBUG? 
     423//         AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it ); 
     424//         assert ( pinfo ); // this should not fail!! 
     425//  
     426//         switch( pinfo->getFormat() ) 
     427//         { 
     428//             case AmdtpPortInfo::E_MBLA: 
     429//                 if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
     430//                 { 
     431//                     debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() ); 
     432//                     no_problem = false; 
     433//                 } 
     434//                 break; 
     435//             case AmdtpPortInfo::E_SPDIF: // still unimplemented 
     436//                 break; 
     437//             case AmdtpPortInfo::E_Midi: 
     438//                 if( encodePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
     439//                 { 
     440//                     debugWarning ( "Could not encode port %s to Midi events", (*it)->getName().c_str() ); 
     441//                     no_problem = false; 
     442//                 } 
     443//                 break; 
     444//             default: // ignore 
     445//                 break; 
     446//         } 
     447//     } 
    433448    return no_problem; 
    434449} 
     
    472487} 
    473488 
    474 #if USE_SSE 
    475 #error Broken 
    476 typedef float v4sf __attribute__ ((vector_size (16))); 
    477 typedef int v4si __attribute__ ((vector_size (16))); 
    478 typedef int v2si __attribute__ ((vector_size (8))); 
    479  
    480489int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    481490        unsigned int offset, unsigned int nevents ) 
    482491{ 
    483     static const float sse_multiplier[4] __attribute__((aligned(16))) = { 
    484         (float)(0x7FFFFF00), 
    485         (float)(0x7FFFFF00), 
    486         (float)(0x7FFFFF00), 
    487         (float)(0x7FFFFF00) 
    488     }; 
    489  
    490     static const int sse_mask[4] __attribute__((aligned(16))) = { 
    491         0x40000000,  0x40000000,  0x40000000,  0x40000000 
    492     }; 
    493  
    494     unsigned int out[4]; 
    495  
    496492    unsigned int j=0; 
    497     unsigned int read=0; 
    498493 
    499494    quadlet_t *target_event; 
     
    524519        case Port::E_Float: 
    525520        { 
    526             const float multiplier = ( float ) ( 0x7FFFFF00 ); 
    527521            float *buffer= ( float * ) ( p->getBufferAddress() ); 
    528  
    529             assert ( nevents + offset <= p->getBufferSize() ); 
    530  
    531             buffer+=offset; 
    532  
    533             j=0; 
    534             if(read>3) { 
    535                 for (j = 0; j < read-3; j += 4) { 
    536                     asm("movups %[floatbuff], %%xmm0\n\t" 
    537                             "mulps %[ssemult], %%xmm0\n\t" 
    538                             "cvttps2pi %%xmm0, %[out1]\n\t" 
    539                             "movhlps %%xmm0, %%xmm0\n\t" 
    540                             "psrld $8, %[out1]\n\t" 
    541                             "cvttps2pi %%xmm0, %[out2]\n\t" 
    542                             "por %[mmxmask], %[out1]\n\t" 
    543                             "psrld $8, %[out2]\n\t" 
    544                             "por %[mmxmask], %[out2]\n\t" 
    545                         : [out1] "=&y" (*(v2si*)&out[0]), 
    546                     [out2] "=&y" (*(v2si*)&out[2]) 
    547                         : [floatbuff] "m" (*(v4sf*)buffer), 
    548                     [ssemult] "x" (*(v4sf*)sse_multiplier), 
    549                     [mmxmask] "y" (*(v2si*)sse_mask) 
    550                         : "xmm0"); 
    551                     buffer += 4; 
    552                     *target_event = htonl(out[0]); 
    553                     target_event += m_dimension; 
    554                     *target_event = htonl(out[1]); 
    555                     target_event += m_dimension; 
    556                     *target_event = htonl(out[2]); 
    557                     target_event += m_dimension; 
    558                     *target_event = htonl(out[3]); 
    559                     target_event += m_dimension; 
    560                 } 
    561             } 
    562             for(; j < read; ++j) { 
    563             // don't care for overflow 
    564                 float v = *buffer * multiplier;  // v: -231 .. 231 
    565                 unsigned int tmp = (int)v; 
    566                 *target_event = htonl((tmp >> 8) | 0x40000000); 
    567      
    568                 buffer++; 
    569                 target_event += m_dimension; 
    570             } 
    571  
    572             asm volatile("emms"); 
    573             break; 
    574         } 
    575         break; 
    576     } 
    577  
    578     return 0; 
    579 } 
    580  
    581 #else 
    582  
    583 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    584         unsigned int offset, unsigned int nevents ) 
    585 { 
    586     unsigned int j=0; 
    587  
    588     quadlet_t *target_event; 
    589  
    590     target_event= ( quadlet_t * ) ( data + p->getPosition() ); 
    591  
    592     switch ( p->getDataType() ) 
    593     { 
    594         default: 
    595             debugError("bad type: %d\n", p->getDataType()); 
    596             return -1; 
    597         case Port::E_Int24: 
    598         { 
    599             quadlet_t *buffer= ( quadlet_t * ) ( p->getBufferAddress() ); 
    600522 
    601523            assert ( nevents + offset <= p->getBufferSize() ); 
     
    605527            for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    606528            { 
    607                 *target_event = htonl ( ( * ( buffer ) & 0x00FFFFFF ) | 0x40000000 ); 
    608                 buffer++; 
    609                 target_event += m_dimension; 
    610             } 
    611         } 
    612         break; 
    613         case Port::E_Float: 
    614         { 
    615             const float multiplier = ( float ) ( 0x7FFFFF00 ); 
    616             float *buffer= ( float * ) ( p->getBufferAddress() ); 
    617  
    618             assert ( nevents + offset <= p->getBufferSize() ); 
    619  
    620             buffer+=offset; 
    621  
    622             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    623             { 
    624529 
    625530                // don't care for overflow 
    626                 float v = *buffer * multiplier;  // v: -231 .. 231 
     531                float v = *buffer * AMDTP_FLOAT_MULTIPLIER;  // v: -231 .. 231 
    627532                unsigned int tmp = ( ( int ) v ); 
    628533                *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 ); 
     
    691596} 
    692597 
    693 #endif 
    694  
    695598int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    696599        unsigned int offset, unsigned int nevents ) 
     
    747650} 
    748651 
     652/** 
     653 * @brief encodes all audio ports in the cache to events 
     654 * @param data  
     655 * @param offset  
     656 * @param nevents  
     657 * @return  
     658 */ 
     659bool 
     660AmdtpTransmitStreamProcessor::encodeAudioPorts(quadlet_t *data, 
     661                                               unsigned int offset, 
     662                                               unsigned int nevents) 
     663{ 
     664    unsigned int j=0; 
     665 
     666    quadlet_t *target_event; 
     667    unsigned int i; 
     668    for (i = 0; i < m_nb_audio_ports; i++) { 
     669        struct _MBLA_port_cache p = m_audio_ports.at(i); 
     670        target_event = (quadlet_t *)(data + i); 
     671        assert(nevents + offset <= p.buffer_size ); 
     672 
     673        switch ( p.type ) 
     674        { 
     675            case Port::E_Float: 
     676            { 
     677                float *buffer = (float *)(p.buffer); 
     678                buffer += offset; 
     679 
     680                for (j = 0;j < nevents; j += 1)   // decode max nsamples 
     681                { 
     682                    // don't care for overflow 
     683                    float v = (*buffer) * AMDTP_FLOAT_MULTIPLIER; 
     684                    unsigned int tmp = ((int) v); 
     685                    *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 ); 
     686                    buffer++; 
     687                    target_event += m_dimension; 
     688                } 
     689            } 
     690            break; 
     691            case Port::E_Int24: 
     692            { 
     693                uint32_t *buffer = (uint32_t *)(p.buffer); 
     694                buffer += offset; 
     695 
     696                for (j = 0; j < nevents; j += 1)   // decode max nsamples 
     697                { 
     698                    *target_event = htonl(((*buffer) & 0x00FFFFFF) | 0x40000000); 
     699                    buffer++; 
     700                    target_event += m_dimension; 
     701                } 
     702            } 
     703            break; 
     704            default: 
     705                debugError("bad type: %d\n", m_audio_ports.at(i).type); 
     706                return false; 
     707        } 
     708    } 
     709    return true; 
     710} 
     711 
     712 
     713bool 
     714AmdtpTransmitStreamProcessor::initPortCache() { 
     715    // make use of the fact that audio ports are the first ports in 
     716    // the cluster as per AMDTP. so we can sort the ports by position 
     717    // and have very efficient lookups: 
     718    // m_float_ports.at(i).buffer -> audio stream i buffer 
     719    m_nb_audio_ports = 0; 
     720    m_audio_ports.clear(); 
     721     
     722    m_nb_midi_ports = 0; 
     723     
     724    for(PortVectorIterator it = m_Ports.begin(); 
     725        it != m_Ports.end(); 
     726        ++it ) 
     727    { 
     728        AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
     729        assert(pinfo); // this should not fail!! 
     730 
     731        switch( pinfo->getFormat() ) 
     732        { 
     733            case AmdtpPortInfo::E_MBLA: 
     734                m_nb_audio_ports++; 
     735                break; 
     736            case AmdtpPortInfo::E_SPDIF: // still unimplemented 
     737                break; 
     738            case AmdtpPortInfo::E_Midi: 
     739                m_nb_midi_ports++; 
     740                break; 
     741            default: // ignore 
     742                break; 
     743        } 
     744    } 
     745 
     746    unsigned int idx; 
     747    for (idx = 0; idx < m_nb_audio_ports; idx++) { 
     748        for(PortVectorIterator it = m_Ports.begin(); 
     749            it != m_Ports.end(); 
     750            ++it ) 
     751        { 
     752            AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
     753            debugOutput(DEBUG_LEVEL_VERBOSE, "idx %u: looking at port %s at position %u\n", 
     754                                              idx, (*it)->getName().c_str(), pinfo->getPosition()); 
     755            if(pinfo->getPosition() == idx) { 
     756                struct _MBLA_port_cache p; 
     757                p.port = dynamic_cast<AmdtpAudioPort *>(*it); 
     758                if(p.port == NULL) { 
     759                    debugError("Port is not an AmdtpAudioPort!\n"); 
     760                    return false; 
     761                } 
     762//                p.position = pinfo->getPosition(); 
     763                p.buffer = NULL; // to be filled by updatePortCache 
     764                p.type = (*it)->getDataType(); 
     765#ifdef DEBUG 
     766                p.buffer_size = (*it)->getBufferSize(); 
     767#endif 
     768 
     769                m_audio_ports.push_back(p); 
     770                debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u\n", 
     771                                                 p.port->getName().c_str(), idx); 
     772                goto next_index; 
     773            } 
     774        } 
     775        debugError("No MBLA port found for position %d\n", idx); 
     776        return false; 
     777next_index: 
     778        continue; 
     779    } 
     780 
     781    return true; 
     782} 
     783 
     784void 
     785AmdtpTransmitStreamProcessor::updatePortCache() { 
     786    unsigned int idx; 
     787    for (idx = 0; idx < m_nb_audio_ports; idx++) { 
     788        AmdtpAudioPort *port = m_audio_ports.at(idx).port; 
     789        m_audio_ports.at(idx).buffer = port->getBufferAddress(); 
     790    } 
     791} 
     792 
    749793} // end of namespace Streaming 
  • branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h

    r809 r815  
    124124                                      unsigned int offset, unsigned int nevents); 
    125125 
     126    bool encodeAudioPorts(quadlet_t *data, unsigned int offset, unsigned int nevents); 
     127 
    126128    unsigned int getFDF(); 
    127129    unsigned int getSytInterval(); 
     
    132134    int m_fdf; 
    133135    unsigned int m_dbc; 
     136 
     137private: // local port caching for performance 
     138    struct _MBLA_port_cache { 
     139        AmdtpAudioPort*     port; 
     140        Port::E_DataType    type; 
     141        void*               buffer; 
     142#ifdef DEBUG 
     143        unsigned int        buffer_size; 
     144#endif 
     145    }; 
     146    std::vector<struct _MBLA_port_cache> m_audio_ports; 
     147    unsigned int m_nb_audio_ports; 
     148    unsigned int m_nb_midi_ports; 
     149 
     150    bool initPortCache(); 
     151    void updatePortCache(); 
     152 
    134153}; 
    135154 
  • branches/api-cleanup/src/libstreaming/generic/StreamProcessor.cpp

    r813 r815  
    474474                    // the process thread should have higher prio such that we are blocked until 
    475475                    // the samples are processed. 
     476                    return RAW1394_ISO_DEFER; 
    476477                } 
    477478            } 
     
    936937    } 
    937938    result = bufferfill > getNominalFramesPerPacket(); 
    938     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) for a bufferfill of %d, we return %d\n", 
    939                 this, ePTToString(getType()), bufferfill, result); 
     939    // debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) for a bufferfill of %d, we return %d\n", 
     940    //             this, ePTToString(getType()), bufferfill, result); 
    940941    return result; 
    941942} 
     
    10511052    if(m_scratch_buffer == NULL) { 
    10521053        debugFatal("Could not allocate scratch buffer\n"); 
     1054        return false; 
     1055    } 
     1056 
     1057    // set the parameters of ports we can: 
     1058    // we want the audio ports to be period buffered, 
     1059    // and the midi ports to be packet buffered 
     1060    for ( PortVectorIterator it = m_Ports.begin(); 
     1061        it != m_Ports.end(); 
     1062        ++it ) 
     1063    { 
     1064        debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
     1065        if(!(*it)->setBufferSize(m_StreamProcessorManager.getPeriodSize())) { 
     1066            debugFatal("Could not set buffer size to %d\n",m_StreamProcessorManager.getPeriodSize()); 
     1067            return false; 
     1068        } 
     1069    } 
     1070    // the API specific settings of the ports should already be set, 
     1071    // as this is called from the processorManager->prepare() 
     1072    // so we can init the ports 
     1073    if(!PortManager::initPorts()) { 
     1074        debugFatal("Could not initialize ports\n"); 
    10531075        return false; 
    10541076    } 
     
    12971319            result &= m_data_buffer->prepare(); // FIXME: the name 
    12981320 
    1299             // set the parameters of ports we can: 
    1300             // we want the audio ports to be period buffered, 
    1301             // and the midi ports to be packet buffered 
    1302             for ( PortVectorIterator it = m_Ports.begin(); 
    1303                 it != m_Ports.end(); 
    1304                 ++it ) 
    1305             { 
    1306                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
    1307                 if(!(*it)->setBufferSize(m_StreamProcessorManager.getPeriodSize())) { 
    1308                     debugFatal("Could not set buffer size to %d\n",m_StreamProcessorManager.getPeriodSize()); 
    1309                     return false; 
    1310                 } 
    1311             } 
    1312             // the API specific settings of the ports should already be set, 
    1313             // as this is called from the processorManager->prepare() 
    1314             // so we can init the ports 
    1315             result &= PortManager::initPorts(); 
    1316  
    13171321            break; 
    13181322        case ePS_DryRunning: