Changeset 712

Show
Ignore:
Timestamp:
11/11/07 07:52:01 (13 years ago)
Author:
ppalmers
Message:

almost there...

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/ppalmers-streaming/src/bebob/bebob_avdevice.h

    r705 r712  
    4242#include "bebob/bebob_mixer.h" 
    4343 
    44 #include "libstreaming/amdtp/AmdtpStreamProcessor.h" 
     44#include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 
     45#include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 
    4546#include "libstreaming/amdtp/AmdtpPort.h" 
    4647#include "libstreaming/amdtp/AmdtpPortInfo.h" 
  • branches/ppalmers-streaming/src/bounce/bounce_avdevice.h

    r705 r712  
    3030#include "libavc/general/avc_extended_cmd_generic.h" 
    3131 
    32 #include "libstreaming/amdtp/AmdtpStreamProcessor.h" 
     32#include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 
     33#include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 
    3334#include "libstreaming/amdtp/AmdtpPort.h" 
    3435#include "libstreaming/amdtp/AmdtpPortInfo.h" 
  • branches/ppalmers-streaming/src/dice/dice_avdevice.cpp

    r705 r712  
    2828#include "libieee1394/ieee1394service.h" 
    2929 
    30 #include "libstreaming/amdtp/AmdtpStreamProcessor.h" 
    31  
    3230#include "debugmodule/debugmodule.h" 
    3331 
     
    5149    // vendor id, model id, vendor name, model name 
    5250    {FW_VENDORID_TCAT, 0x00000002, "TCAT", "DiceII EVM"}, 
     51    {FW_VENDORID_TCAT, 0x00000004, "TCAT", "DiceII EVM (vxx)"}, 
    5352}; 
    5453 
  • branches/ppalmers-streaming/src/dice/dice_avdevice.h

    r705 r712  
    3030#include "libavc/avc_definitions.h" 
    3131 
    32 #include "libstreaming/amdtp/AmdtpStreamProcessor.h" 
     32#include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 
     33#include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 
    3334#include "libstreaming/amdtp/AmdtpPort.h" 
    3435#include "libieee1394/ARMHandler.h" 
  • branches/ppalmers-streaming/src/genericavc/avc_avdevice.h

    r705 r712  
    3434#include "libavc/general/avc_plug.h" 
    3535 
    36 #include "libstreaming/amdtp/AmdtpStreamProcessor.h" 
     36#include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 
     37#include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 
    3738#include "libstreaming/amdtp/AmdtpPort.h" 
    3839#include "libstreaming/amdtp/AmdtpPortInfo.h" 
  • branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp

    r709 r712  
    2222 */ 
    2323 
    24 #include "AmdtpStreamProcessor.h" 
     24#include "AmdtpReceiveStreamProcessor.h" 
    2525#include "AmdtpPort.h" 
    2626 
     
    3939namespace Streaming { 
    4040 
    41 /* transmit */ 
    42 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(int port, int framerate, int dimension) 
    43         : TransmitStreamProcessor(port, framerate), m_dimension(dimension) 
    44         , m_last_timestamp(0), m_dbc(0), m_ringbuffer_size_frames(0) 
    45 {} 
    46  
    47 /** 
    48  * @return 
    49  */ 
    50 bool AmdtpTransmitStreamProcessor::init() { 
    51  
    52     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing (%p)...\n"); 
    53     // call the parent init 
    54     // this has to be done before allocating the buffers, 
    55     // because this sets the buffersizes from the processormanager 
    56     if(!TransmitStreamProcessor::init()) { 
    57         debugFatal("Could not do base class init (%p)\n",this); 
    58         return false; 
    59     } 
    60     return true; 
    61 } 
    62  
    63 enum raw1394_iso_disposition 
    64 AmdtpTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length, 
    65                   unsigned char *tag, unsigned char *sy, 
    66                   int cycle, unsigned int dropped, unsigned int max_length) { 
    67     struct iec61883_packet *packet = (struct iec61883_packet *) data; 
    68  
    69     if (cycle<0) { 
    70         debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,"Xmit handler for cycle %d, (running=%d)\n", 
    71             cycle, m_running); 
    72         *tag = 0; 
    73         *sy = 0; 
    74         *length=0; 
    75         return RAW1394_ISO_OK; 
    76     } 
    77  
    78     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,"Xmit handler for cycle %d, (running=%d)\n", 
    79         cycle, m_running); 
    80  
    81     m_last_cycle=cycle; 
    82  
    83 #ifdef DEBUG 
    84     if(dropped>0) { 
    85         debugWarning("Dropped %d packets on cycle %d\n",dropped, cycle); 
    86     } 
    87 #endif 
    88  
    89     // calculate & preset common values 
    90  
    91     /* Our node ID can change after a bus reset, so it is best to fetch 
    92      * our node ID for each packet. */ 
    93     packet->sid = getNodeId() & 0x3f; 
    94  
    95     packet->dbs = m_dimension; 
    96     packet->fn = 0; 
    97     packet->qpc = 0; 
    98     packet->sph = 0; 
    99     packet->reserved = 0; 
    100     packet->dbc = m_dbc; 
    101     packet->eoh1 = 2; 
    102     packet->fmt = IEC61883_FMT_AMDTP; 
    103  
    104     *tag = IEC61883_TAG_WITH_CIP; 
    105     *sy = 0; 
    106  
    107     // determine if we want to send a packet or not 
    108     // note that we can't use getCycleTimer directly here, 
    109     // because packets are queued in advance. This means that 
    110     // we the packet we are constructing will be sent out 
    111     // on 'cycle', not 'now'. 
    112     unsigned int ctr=m_handler->getCycleTimer(); 
    113     int now_cycles = (int)CYCLE_TIMER_GET_CYCLES(ctr); 
    114  
    115     // the difference between the cycle this 
    116     // packet is intended for and 'now' 
    117     int cycle_diff = diffCycles(cycle, now_cycles); 
    118  
    119 #ifdef DEBUG 
    120     if(m_running && (cycle_diff < 0)) { 
    121         debugWarning("Requesting packet for cycle %04d which is in the past (now=%04dcy)\n", 
    122             cycle, now_cycles); 
    123     } 
    124  
    125     // keep track of the lag 
    126     m_PacketStat.mark(cycle_diff); 
    127 #endif 
    128  
    129     // as long as the cycle parameter is not in sync with 
    130     // the current time, the stream is considered not 
    131     // to be 'running' 
    132     // NOTE: this works only at startup 
    133     if (!m_running && cycle_diff >= 0 && cycle >= 0) { 
    134             debugOutput(DEBUG_LEVEL_VERBOSE, "Xmit StreamProcessor %p started running at cycle %d\n",this, cycle); 
    135             m_running=true; 
    136     } 
    137  
    138     signed int fc; 
    139     uint64_t presentation_time; 
    140     unsigned int presentation_cycle; 
    141     int cycles_until_presentation; 
    142  
    143     uint64_t transmit_at_time; 
    144     unsigned int transmit_at_cycle; 
    145     int cycles_until_transmit; 
    146  
    147     // FIXME: should become a define 
    148     // the absolute minimum number of cycles we want to transmit 
    149     // a packet ahead of the presentation time. The nominal time 
    150     // the packet is transmitted ahead of the presentation time is 
    151     // given by TRANSMIT_TRANSFER_DELAY (in ticks), but in case we 
    152     // are too late for that, this constant defines how late we can 
    153     // be. 
    154     const int min_cycles_before_presentation = 1; 
    155     // FIXME: should become a define 
    156     // the absolute maximum number of cycles we want to transmit 
    157     // a packet ahead of the ideal transmit time. The nominal time 
    158     // the packet is transmitted ahead of the presentation time is 
    159     // given by TRANSMIT_TRANSFER_DELAY (in ticks), but we can send 
    160     // packets early if we want to. (not completely according to spec) 
    161     const int max_cycles_to_transmit_early = 1; 
    162  
    163     if( !m_running || !m_data_buffer->isEnabled() ) { 
    164         debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, 
    165                     "Not running (%d) or buffer not enabled (enabled=%d)\n", 
    166                     m_running, m_data_buffer->isEnabled()); 
    167  
    168         // not running or not enabled 
    169         goto send_empty_packet; 
    170     } 
    171  
    172 try_block_of_frames: 
    173     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "Try for cycle %d\n", cycle); 
    174     // check whether the packet buffer has packets for us to send. 
    175     // the base timestamp is the one of the next sample in the buffer 
    176     ffado_timestamp_t ts_head_tmp; 
    177     m_data_buffer->getBufferHeadTimestamp(&ts_head_tmp, &fc); // thread safe 
    178  
    179     // the timestamp gives us the time at which we want the sample block 
    180     // to be output by the device 
    181     presentation_time=(uint64_t)ts_head_tmp; 
    182  
    183     // now we calculate the time when we have to transmit the sample block 
    184     transmit_at_time = substractTicks(presentation_time, TRANSMIT_TRANSFER_DELAY); 
    185  
    186     // calculate the cycle this block should be presented in 
    187     // (this is just a virtual calculation since at that time it should 
    188     //  already be in the device's buffer) 
    189     presentation_cycle = (unsigned int)(TICKS_TO_CYCLES( presentation_time )); 
    190  
    191     // calculate the cycle this block should be transmitted in 
    192     transmit_at_cycle = (unsigned int)(TICKS_TO_CYCLES( transmit_at_time )); 
    193  
    194     // we can check whether this cycle is within the 'window' we have 
    195     // to send this packet. 
    196     // first calculate the number of cycles left before presentation time 
    197     cycles_until_presentation = diffCycles( presentation_cycle, cycle ); 
    198  
    199     // we can check whether this cycle is within the 'window' we have 
    200     // to send this packet. 
    201     // first calculate the number of cycles left before presentation time 
    202     cycles_until_transmit = diffCycles( transmit_at_cycle, cycle ); 
    203  
    204     // two different options: 
    205     // 1) there are not enough frames for one packet  
    206     //      => determine wether this is a problem, since we might still 
    207     //         have some time to send it 
    208     // 2) there are enough packets 
    209     //      => determine whether we have to send them in this packet 
    210     if (fc < (signed int)m_syt_interval) { 
    211         m_PacketStat.signal(0); 
    212         // not enough frames in the buffer, 
    213         debugOutput(DEBUG_LEVEL_VERBOSE,  
    214                     "Insufficient frames: N=%02d, CY=%04u, TC=%04u, CUT=%04d\n", 
    215                     fc, cycle, transmit_at_cycle, cycles_until_transmit); 
    216         // we can still postpone the queueing of the packets 
    217         // if we are far enough ahead of the presentation time 
    218         if( cycles_until_presentation <= min_cycles_before_presentation ) { 
    219             m_PacketStat.signal(1); 
    220             // we are too late 
    221             // meaning that we in some sort of xrun state 
    222             // signal xrun situation ??HERE?? 
    223             m_xruns++; 
    224             // we send an empty packet on this cycle 
    225             goto send_empty_packet; // UGLY but effective 
    226         } else { 
    227             m_PacketStat.signal(2); 
    228             // there is still time left to send the packet 
    229             // we want the system to give this packet another go 
    230 //             goto try_packet_again; // UGLY but effective 
    231             // unfortunatly the try_again doesn't work very well, 
    232             // so we'll have to either usleep(one cycle) and goto try_block_of_frames 
    233              
    234             // or just fill this with an empty packet 
    235             // if we have to do this too often, the presentation time will 
    236             // get too close and we're in trouble 
    237             goto send_empty_packet; // UGLY but effective 
    238         } 
    239     } else { 
    240         m_PacketStat.signal(3); 
    241         // there are enough frames, so check the time they are intended for 
    242         // all frames have a certain 'time window' in which they can be sent 
    243         // this corresponds to the range of the timestamp mechanism: 
    244         // we can send a packet 15 cycles in advance of the 'presentation time' 
    245         // in theory we can send the packet up till one cycle before the presentation time, 
    246         // however this is not very smart. 
    247          
    248         // There are 3 options: 
    249         // 1) the frame block is too early 
    250         //      => send an empty packet 
    251         // 2) the frame block is within the window 
    252         //      => send it 
    253         // 3) the frame block is too late 
    254         //      => discard (and raise xrun?) 
    255         //         get next block of frames and repeat 
    256          
    257         if (cycles_until_transmit <= max_cycles_to_transmit_early) { 
    258             m_PacketStat.signal(4); 
    259             // it's time send the packet 
    260             goto send_packet; // UGLY but effective 
    261         } else if (cycles_until_transmit < 0) { 
    262             // we are too late 
    263             debugOutput(DEBUG_LEVEL_VERBOSE,  
    264                         "Too late: CY=%04u, TC=%04u, CUT=%04d, TSP=%011llu (%04u)\n", 
    265                         cycle, 
    266                         transmit_at_cycle, cycles_until_transmit, 
    267                         presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 
    268  
    269             // however, if we can send this sufficiently before the presentation 
    270             // time, it could be harmless. 
    271             // NOTE: dangerous since the device has no way of reporting that it didn't get 
    272             //       this packet on time. 
    273             if ( cycles_until_presentation <= min_cycles_before_presentation ) { 
    274                 m_PacketStat.signal(5); 
    275                 // we are not that late and can still try to transmit the packet 
    276                 goto send_packet; // UGLY but effective 
    277             } else { // definitely too late 
    278                 m_PacketStat.signal(6); 
    279                 // remove the samples 
    280                 m_data_buffer->dropFrames(m_syt_interval); 
    281                 // signal some xrun situation ??HERE?? 
    282                 m_xruns++; 
    283                 // try a new block of frames 
    284                 goto try_block_of_frames; // UGLY but effective 
    285             } 
    286         } else { 
    287             m_PacketStat.signal(7); 
    288             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,  
    289                         "Too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n", 
    290                         cycle, 
    291                         transmit_at_cycle, cycles_until_transmit, 
    292                         transmit_at_time, (unsigned int)TICKS_TO_CYCLES(transmit_at_time), 
    293                         presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 
    294             #ifdef DEBUG 
    295             if (cycles_until_transmit > max_cycles_to_transmit_early + 1) { 
    296                 debugOutput(DEBUG_LEVEL_VERBOSE,  
    297                             "Way too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n", 
    298                             cycle, 
    299                             transmit_at_cycle, cycles_until_transmit, 
    300                             transmit_at_time, (unsigned int)TICKS_TO_CYCLES(transmit_at_time), 
    301                             presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 
    302             } 
    303             #endif 
    304             // we are too early, send only an empty packet 
    305             goto send_empty_packet; // UGLY but effective 
    306         } 
    307     } 
    308  
    309     debugFatal("Should never reach this code!\n"); 
    310     return RAW1394_ISO_ERROR; 
    311  
    312 send_empty_packet: 
    313     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT NONE: CY=%04u, TSP=%011llu (%04u)\n", 
    314             cycle, 
    315             presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 
    316  
    317     m_dbc += fillNoDataPacketHeader(packet, length); 
    318     return RAW1394_ISO_DEFER; 
    319  
    320 send_packet: 
    321     if (m_data_buffer->readFrames(m_syt_interval, (char *)(data + 8))) { 
    322         m_dbc += fillDataPacketHeader(packet, length, presentation_time); 
    323  
    324         // process all ports that should be handled on a per-packet base 
    325         // this is MIDI for AMDTP (due to the need of DBC) 
    326         if (!encodePacketPorts((quadlet_t *)(data+8), m_syt_interval, packet->dbc)) { 
    327             debugWarning("Problem encoding Packet Ports\n"); 
    328         } 
    329  
    330         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT DATA: CY=%04u, TST=%011llu (%04u), TSP=%011llu (%04u)\n", 
    331             cycle, 
    332             transmit_at_time, (unsigned int)TICKS_TO_CYCLES(transmit_at_time), 
    333             presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 
    334  
    335         return RAW1394_ISO_OK; 
    336     } 
    337  
    338 // the ISO AGAIN does not work very well... 
    339 // try_packet_again: 
    340 //  
    341 //     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT RETRY: CY=%04u, TSP=%011llu (%04u)\n", 
    342 //             cycle, 
    343 //             presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 
    344 //     return RAW1394_ISO_AGAIN; 
    345  
    346     // else: 
    347     debugFatal("This is impossible, since we checked the buffer size before!\n"); 
    348     return RAW1394_ISO_ERROR; 
    349 } 
    350  
    351 unsigned int AmdtpTransmitStreamProcessor::fillDataPacketHeader( 
    352         struct iec61883_packet *packet, unsigned int* length, 
    353         uint32_t ts) { 
    354  
    355     packet->fdf = m_fdf; 
    356  
    357     // convert the timestamp to SYT format 
    358     uint16_t timestamp_SYT = TICKS_TO_SYT(ts); 
    359     packet->syt = ntohs(timestamp_SYT); 
    360  
    361     *length = m_syt_interval*sizeof(quadlet_t)*m_dimension + 8; 
    362  
    363     return m_syt_interval; 
    364 } 
    365  
    366 unsigned int AmdtpTransmitStreamProcessor::fillNoDataPacketHeader( 
    367         struct iec61883_packet *packet, unsigned int* length) { 
    368  
    369     // no-data packets have syt=0xFFFF 
    370     // and have the usual amount of events as dummy data (?) 
    371     packet->fdf = IEC61883_FDF_NODATA; 
    372     packet->syt = 0xffff; 
    373  
    374     // FIXME: either make this a setting or choose 
    375     bool send_payload=true; 
    376     if(send_payload) { 
    377         // this means no-data packets with payload (DICE doesn't like that) 
    378         *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t); 
    379         return m_syt_interval; 
    380     } else { 
    381         // dbc is not incremented 
    382         // this means no-data packets without payload 
    383         *length = 2*sizeof(quadlet_t); 
    384         return 0; 
    385     } 
    386 } 
    387  
    388 bool AmdtpTransmitStreamProcessor::prefill() { 
    389  
    390     debugOutput( DEBUG_LEVEL_VERBOSE, "Prefill transmit buffers...\n"); 
    391  
    392     if(!transferSilence(m_ringbuffer_size_frames)) { 
    393         debugFatal("Could not prefill transmit stream\n"); 
    394         return false; 
    395     } 
    396  
    397     return true; 
    398 } 
    399  
    400 bool AmdtpTransmitStreamProcessor::reset() { 
    401  
    402     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n"); 
    403  
    404     // reset the statistics 
    405     m_PeriodStat.reset(); 
    406     m_PacketStat.reset(); 
    407     m_WakeupStat.reset(); 
    408  
    409     m_data_buffer->setTickOffset(0); 
    410  
    411     // reset all non-device specific stuff 
    412     // i.e. the iso stream and the associated ports 
    413     if(!TransmitStreamProcessor::reset()) { 
    414         debugFatal("Could not do base class reset\n"); 
    415         return false; 
    416     } 
    417  
    418     // we should prefill the event buffer 
    419     if (!prefill()) { 
    420         debugFatal("Could not prefill buffers\n"); 
    421         return false; 
    422     } 
    423  
    424     return true; 
    425 } 
    426  
    427 bool AmdtpTransmitStreamProcessor::prepare() { 
    428     m_PeriodStat.setName("XMT PERIOD"); 
    429     m_PacketStat.setName("XMT PACKET"); 
    430     m_WakeupStat.setName("XMT WAKEUP"); 
    431  
    432     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this); 
    433  
    434     // prepare all non-device specific stuff 
    435     // i.e. the iso stream and the associated ports 
    436     if(!TransmitStreamProcessor::prepare()) { 
    437         debugFatal("Could not prepare base class\n"); 
    438         return false; 
    439     } 
    440  
    441     switch (m_framerate) { 
    442     case 32000: 
    443         m_syt_interval = 8; 
    444         m_fdf = IEC61883_FDF_SFC_32KHZ; 
    445         break; 
    446     case 44100: 
    447         m_syt_interval = 8; 
    448         m_fdf = IEC61883_FDF_SFC_44K1HZ; 
    449         break; 
    450     default: 
    451     case 48000: 
    452         m_syt_interval = 8; 
    453         m_fdf = IEC61883_FDF_SFC_48KHZ; 
    454         break; 
    455     case 88200: 
    456         m_syt_interval = 16; 
    457         m_fdf = IEC61883_FDF_SFC_88K2HZ; 
    458         break; 
    459     case 96000: 
    460         m_syt_interval = 16; 
    461         m_fdf = IEC61883_FDF_SFC_96KHZ; 
    462         break; 
    463     case 176400: 
    464         m_syt_interval = 32; 
    465         m_fdf = IEC61883_FDF_SFC_176K4HZ; 
    466         break; 
    467     case 192000: 
    468         m_syt_interval = 32; 
    469         m_fdf = IEC61883_FDF_SFC_192KHZ; 
    470         break; 
    471     } 
    472  
    473     iec61883_cip_init ( 
    474         &m_cip_status, 
    475         IEC61883_FMT_AMDTP, 
    476         m_fdf, 
    477         m_framerate, 
    478         m_dimension, 
    479         m_syt_interval); 
    480  
    481     // prepare the framerate estimate 
    482     float ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate); 
    483     m_ticks_per_frame=ticks_per_frame; 
    484  
    485     // initialize internal buffer 
    486     m_ringbuffer_size_frames=m_nb_buffers * m_period; 
    487  
    488     assert(m_data_buffer); 
    489     m_data_buffer->setBufferSize(m_ringbuffer_size_frames); 
    490     m_data_buffer->setEventSize(sizeof(quadlet_t)); 
    491     m_data_buffer->setEventsPerFrame(m_dimension); 
    492  
    493     m_data_buffer->setUpdatePeriod(m_period); 
    494     m_data_buffer->setNominalRate(ticks_per_frame); 
    495  
    496     m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND); 
    497  
    498     m_data_buffer->prepare(); 
    499  
    500     // set the parameters of ports we can: 
    501     // we want the audio ports to be period buffered, 
    502     // and the midi ports to be packet buffered 
    503     for ( PortVectorIterator it = m_Ports.begin(); 
    504           it != m_Ports.end(); 
    505           ++it ) 
    506     { 
    507         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
    508         if(!(*it)->setBufferSize(m_period)) { 
    509             debugFatal("Could not set buffer size to %d\n",m_period); 
    510             return false; 
    511         } 
    512  
    513  
    514         switch ((*it)->getPortType()) { 
    515             case Port::E_Audio: 
    516                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) { 
    517                     debugFatal("Could not set signal type to PeriodSignalling"); 
    518                     return false; 
    519                 } 
    520                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); 
    521                 // buffertype and datatype are dependant on the API 
    522                 if(!(*it)->setBufferType(Port::E_PointerBuffer)) { 
    523                     debugFatal("Could not set buffer type"); 
    524                     return false; 
    525                 } 
    526                 if(!(*it)->useExternalBuffer(true)) { 
    527                     debugFatal("Could not set external buffer usage"); 
    528                     return false; 
    529                 } 
    530  
    531                 if(!(*it)->setDataType(Port::E_Float)) { 
    532                     debugFatal("Could not set data type"); 
    533                     return false; 
    534                 } 
    535  
    536  
    537                 break; 
    538             case Port::E_Midi: 
    539                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) { 
    540                     debugFatal("Could not set signal type to PeriodSignalling"); 
    541                     return false; 
    542                 } 
    543  
    544                 // we use a timing unit of 10ns 
    545                 // this makes sure that for the max syt interval 
    546                 // we don't have rounding, and keeps the numbers low 
    547                 // we have 1 slot every 8 events 
    548                 // we have syt_interval events per packet 
    549                 // => syt_interval/8 slots per packet 
    550                 // packet rate is 8000pkt/sec => interval=125us 
    551                 // so the slot interval is (1/8000)/(syt_interval/8) 
    552                 // or: 1/(1000 * syt_interval) sec 
    553                 // which is 1e9/(1000*syt_interval) nsec 
    554                 // or 100000/syt_interval 'units' 
    555                 // the event interval is fixed to 320us = 32000 'units' 
    556                 if(!(*it)->useRateControl(true,(100000/m_syt_interval),32000, false)) { 
    557                     debugFatal("Could not set signal type to PeriodSignalling"); 
    558                     return false; 
    559                 } 
    560  
    561                 // buffertype and datatype are dependant on the API 
    562                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); 
    563                 // buffertype and datatype are dependant on the API 
    564                 if(!(*it)->setBufferType(Port::E_RingBuffer)) { 
    565                     debugFatal("Could not set buffer type"); 
    566                     return false; 
    567                 } 
    568                 if(!(*it)->setDataType(Port::E_MidiEvent)) { 
    569                     debugFatal("Could not set data type"); 
    570                     return false; 
    571                 } 
    572                 break; 
    573             default: 
    574                 debugWarning("Unsupported port type specified\n"); 
    575                 break; 
    576         } 
    577     } 
    578  
    579     // the API specific settings of the ports should already be set, 
    580     // as this is called from the processorManager->prepare() 
    581     // so we can init the ports 
    582     if(!initPorts()) { 
    583         debugFatal("Could not initialize ports!\n"); 
    584         return false; 
    585     } 
    586  
    587     if(!preparePorts()) { 
    588         debugFatal("Could not initialize ports!\n"); 
    589         return false; 
    590     } 
    591  
    592     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n"); 
    593     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, FDF: %d, DBS: %d, SYT: %d\n", 
    594              m_framerate,m_fdf,m_dimension,m_syt_interval); 
    595     debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n", 
    596              m_period,m_nb_buffers); 
    597     debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n", 
    598              m_port,m_channel); 
    599  
    600     return true; 
    601  
    602 } 
    603  
    604 bool AmdtpTransmitStreamProcessor::prepareForStart() { 
    605     return true; 
    606 } 
    607  
    608 bool AmdtpTransmitStreamProcessor::prepareForStop() { 
    609     return true; 
    610 } 
    611  
    612 bool AmdtpTransmitStreamProcessor::prepareForEnable(uint64_t time_to_enable_at) { 
    613  
    614     if (!StreamProcessor::prepareForEnable(time_to_enable_at)) { 
    615         debugError("StreamProcessor::prepareForEnable failed\n"); 
    616         return false; 
    617     } 
    618  
    619     return true; 
    620 } 
    621  
    622 bool AmdtpTransmitStreamProcessor::transferSilence(unsigned int nframes) { 
    623     bool retval; 
    624  
    625     char *dummybuffer=(char *)calloc(sizeof(quadlet_t),nframes*m_dimension); 
    626  
    627     transmitSilenceBlock(dummybuffer, nframes, 0); 
    628  
    629     // add the silence data to the ringbuffer 
    630     if(m_data_buffer->writeFrames(nframes, dummybuffer, 0)) { 
    631         retval=true; 
    632     } else { 
    633         debugWarning("Could not write to event buffer\n"); 
    634         retval=false; 
    635     } 
    636  
    637     free(dummybuffer); 
    638  
    639     return retval; 
    640 } 
    641  
    642 bool AmdtpTransmitStreamProcessor::putFrames(unsigned int nbframes, int64_t ts) { 
    643     m_PeriodStat.mark(m_data_buffer->getBufferFill()); 
    644     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "AmdtpTransmitStreamProcessor::putFrames(%d, %llu)\n", nbframes, ts); 
    645  
    646     // transfer the data 
    647     m_data_buffer->blockProcessWriteFrames(nbframes, ts); 
    648  
    649     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, " New timestamp: %llu\n", ts); 
    650  
    651     return true; // FIXME: what about failure? 
    652 } 
    653  
    654 bool AmdtpTransmitStreamProcessor::putFramesDry(unsigned int nbframes, int64_t ts) { 
    655     m_PeriodStat.mark(m_data_buffer->getBufferFill()); 
    656     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "AmdtpTransmitStreamProcessor::putFramesDry(%d, %llu)\n", nbframes, ts); 
    657  
    658     bool retval; 
    659     char dummybuffer[sizeof(quadlet_t)*nbframes*m_dimension]; 
    660  
    661     transmitSilenceBlock(dummybuffer, nbframes, 0); 
    662     // add the silence data to the ringbuffer 
    663     if(m_data_buffer->writeFrames(nbframes, dummybuffer, ts)) { 
    664         retval=true; 
    665     } else { 
    666         debugWarning("Could not write to event buffer\n"); 
    667         retval=false; 
    668     } 
    669  
    670     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, " New timestamp: %llu\n", ts); 
    671     return retval; 
    672 } 
    673  
    674 /* 
    675  * write received events to the stream ringbuffers. 
    676  */ 
    677  
    678 bool AmdtpTransmitStreamProcessor::processWriteBlock(char *data, 
    679                        unsigned int nevents, unsigned int offset) 
    680 { 
    681     bool no_problem=true; 
    682  
    683     for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    684           it != m_PeriodPorts.end(); 
    685           ++it ) 
    686     { 
    687  
    688         if((*it)->isDisabled()) {continue;}; 
    689  
    690         //FIXME: make this into a static_cast when not DEBUG? 
    691  
    692         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    693         assert(pinfo); // this should not fail!! 
    694  
    695         switch(pinfo->getFormat()) { 
    696         case AmdtpPortInfo::E_MBLA: 
    697             if(encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    698                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
    699                 no_problem=false; 
    700             } 
    701             break; 
    702         case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    703             break; 
    704         default: // ignore 
    705             break; 
    706         } 
    707     } 
    708     return no_problem; 
    709  
    710 } 
    711  
    712 int AmdtpTransmitStreamProcessor::transmitSilenceBlock(char *data, 
    713                        unsigned int nevents, unsigned int offset) 
    714 { 
    715     int problem=0; 
    716  
    717     for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    718           it != m_PeriodPorts.end(); 
    719           ++it ) 
    720     { 
    721  
    722         //FIXME: make this into a static_cast when not DEBUG? 
    723  
    724         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    725         assert(pinfo); // this should not fail!! 
    726  
    727         switch(pinfo->getFormat()) { 
    728         case AmdtpPortInfo::E_MBLA: 
    729             if(encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    730                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
    731                 problem=1; 
    732             } 
    733             break; 
    734         case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    735             break; 
    736         default: // ignore 
    737             break; 
    738         } 
    739     } 
    740     return problem; 
    741  
    742 } 
    743  
    744 /** 
    745  * @brief decode a packet for the packet-based ports 
    746  * 
    747  * @param data Packet data 
    748  * @param nevents number of events in data (including events of other ports & port types) 
    749  * @param dbc DataBlockCount value for this packet 
    750  * @return true if all successfull 
    751  */ 
    752 bool AmdtpTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc) 
    753 { 
    754     bool ok=true; 
    755     quadlet_t byte; 
    756  
    757     quadlet_t *target_event=NULL; 
    758     unsigned int j; 
    759  
    760     for ( PortVectorIterator it = m_PacketPorts.begin(); 
    761           it != m_PacketPorts.end(); 
    762           ++it ) 
    763     { 
    764  
    765 #ifdef DEBUG 
    766         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    767         assert(pinfo); // this should not fail!! 
    768  
    769         // the only packet type of events for AMDTP is MIDI in mbla 
    770         assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi); 
    771 #endif 
    772  
    773         AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it); 
    774  
    775         // we encode this directly (no function call) due to the high frequency 
    776         /* idea: 
    777         spec says: current_midi_port=(dbc+j)%8; 
    778         => if we start at (dbc+stream->location-1)%8, 
    779         we'll start at the right event for the midi port. 
    780         => if we increment j with 8, we stay at the right event. 
    781         */ 
    782         // FIXME: as we know in advance how big a packet is (syt_interval) we can 
    783         //        predict how much loops will be present here 
    784         // first prefill the buffer with NO_DATA's on all time muxed channels 
    785  
    786         for(j = (dbc & 0x07)+mp->getLocation(); j < nevents; j += 8) { 
    787              
    788             quadlet_t tmpval; 
    789              
    790             target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); 
    791              
    792             if(mp->canRead()) { // we can send a byte 
    793                 mp->readEvent(&byte); 
    794                 byte &= 0xFF; 
    795                 tmpval=htonl( 
    796                     IEC61883_AM824_SET_LABEL((byte)<<16, 
    797                                              IEC61883_AM824_LABEL_MIDI_1X)); 
    798  
    799                 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "MIDI port %s, pos=%d, loc=%d, dbc=%d, nevents=%d, dim=%d\n", 
    800                     mp->getName().c_str(), mp->getPosition(), mp->getLocation(), dbc, nevents, m_dimension); 
    801                 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "base=%p, target=%p, value=%08X\n", 
    802                     data, target_event, tmpval); 
    803                      
    804             } else { 
    805                 // can't send a byte, either because there is no byte, 
    806                 // or because this would exceed the maximum rate 
    807                 tmpval=htonl( 
    808                     IEC61883_AM824_SET_LABEL(0,IEC61883_AM824_LABEL_MIDI_NO_DATA)); 
    809             } 
    810              
    811             *target_event=tmpval; 
    812         } 
    813  
    814     } 
    815  
    816     return ok; 
    817 } 
    818  
    819  
    820 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents(AmdtpAudioPort *p, quadlet_t *data, 
    821                        unsigned int offset, unsigned int nevents) 
    822 { 
    823     unsigned int j=0; 
    824  
    825     quadlet_t *target_event; 
    826  
    827     target_event=(quadlet_t *)(data + p->getPosition()); 
    828  
    829     switch(p->getDataType()) { 
    830         default: 
    831         case Port::E_Int24: 
    832             { 
    833                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
    834  
    835                 assert(nevents + offset <= p->getBufferSize()); 
    836  
    837                 buffer+=offset; 
    838  
    839                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    840                     *target_event = htonl((*(buffer) & 0x00FFFFFF) | 0x40000000); 
    841                     buffer++; 
    842                     target_event += m_dimension; 
    843                 } 
    844             } 
    845             break; 
    846         case Port::E_Float: 
    847             { 
    848                 const float multiplier = (float)(0x7FFFFF00); 
    849                 float *buffer=(float *)(p->getBufferAddress()); 
    850  
    851                 assert(nevents + offset <= p->getBufferSize()); 
    852  
    853                 buffer+=offset; 
    854  
    855                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    856  
    857                     // don't care for overflow 
    858                     float v = *buffer * multiplier;  // v: -231 .. 231 
    859                     unsigned int tmp = ((int)v); 
    860                     *target_event = htonl((tmp >> 8) | 0x40000000); 
    861  
    862                     buffer++; 
    863                     target_event += m_dimension; 
    864                 } 
    865             } 
    866             break; 
    867     } 
    868  
    869     return 0; 
    870 } 
    871 int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents(AmdtpAudioPort *p, quadlet_t *data, 
    872                        unsigned int offset, unsigned int nevents) 
    873 { 
    874     unsigned int j=0; 
    875  
    876     quadlet_t *target_event; 
    877  
    878     target_event=(quadlet_t *)(data + p->getPosition()); 
    879  
    880     switch(p->getDataType()) { 
    881         default: 
    882         case Port::E_Int24: 
    883         case Port::E_Float: 
    884             { 
    885                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    886                     *target_event = htonl(0x40000000); 
    887                     target_event += m_dimension; 
    888                 } 
    889             } 
    890             break; 
    891     } 
    892  
    893     return 0; 
    894 } 
    895  
    89641/* --------------------- RECEIVE ----------------------- */ 
    89742 
    89843AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int port, int framerate, int dimension) 
    899     : ReceiveStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0), m_last_timestamp2(0)  
     44    : ReceiveStreamProcessor(port, framerate) 
     45    , m_dimension(dimension) 
     46    , m_last_timestamp(0) 
     47    , m_last_timestamp2(0) 
     48    , m_dropped(0)  
    90049{} 
    90150 
     
    91867 
    91968    enum raw1394_iso_disposition retval=RAW1394_ISO_OK; 
     69 
     70    int dropped_cycles=diffCycles(cycle, m_last_cycle) - 1; 
     71    if (dropped_cycles < 0) debugWarning("(%p) dropped < 1 (%d)\n", this, dropped_cycles); 
     72    else m_dropped += dropped_cycles; 
     73    if (dropped_cycles > 0) debugWarning("(%p) dropped %d packets on cycle %u\n", this, dropped_cycles, cycle); 
     74 
    92075    m_last_cycle=cycle; 
    92176 
     
    92580#ifdef DEBUG 
    92681    if(dropped>0) { 
    927         debugWarning("Dropped %d packets on cycle %d\n",dropped, cycle); 
     82        debugWarning("(%p) Dropped %d packets on cycle %d\n", this, dropped, cycle); 
    92883    } 
    92984 
     
    956111        m_last_timestamp2=m_last_timestamp; 
    957112 
     113        uint64_t nowX = m_handler->getCycleTimer(); 
    958114        //=> convert the SYT to a full timestamp in ticks 
    959115        m_last_timestamp=sytRecvToFullTicks((uint32_t)ntohs(packet->syt), 
    960                                         cycle, m_handler->getCycleTimer()); 
     116                                        cycle, nowX); 
     117 
     118        int64_t diffx = diffTicks(m_last_timestamp, m_last_timestamp2); 
     119        if (abs(diffx) > m_syt_interval * m_data_buffer->getRate() * 1.1) { 
     120            uint32_t now=m_handler->getCycleTimer(); 
     121            uint32_t syt = (uint32_t)ntohs(packet->syt); 
     122            uint32_t now_ticks=CYCLE_TIMER_TO_TICKS(now); 
     123             
     124            debugOutput(DEBUG_LEVEL_VERBOSE, "diff=%06lld TS=%011llu TS2=%011llu\n", 
     125                diffx, m_last_timestamp, m_last_timestamp2); 
     126            debugOutput(DEBUG_LEVEL_VERBOSE, "[1] cy=%04d dropped=%05llu syt=%04llX NOW=%08llX => TS=%011llu\n", 
     127                m_last_good_cycle, m_last_dropped, m_last_syt, m_last_now, m_last_timestamp2); 
     128            debugOutput(DEBUG_LEVEL_VERBOSE, "[2] cy=%04d dropped=%05d syt=%04X NOW=%08llX => TS=%011llu\n", 
     129                cycle, dropped_cycles, ntohs(packet->syt), nowX, m_last_timestamp); 
     130 
     131            uint32_t test_ts=sytRecvToFullTicks(syt, cycle, now); 
     132 
     133            debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: SYT=%08X,            CY=%04d OFF=%04d\n", 
     134                cycle, syt, CYCLE_TIMER_GET_CYCLES(syt), CYCLE_TIMER_GET_OFFSET(syt) 
     135                ); 
     136            debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: NOW=%011lu, SEC=%03u CY=%04u OFF=%04u\n", 
     137                cycle, now_ticks, CYCLE_TIMER_GET_SECS(now), CYCLE_TIMER_GET_CYCLES(now), CYCLE_TIMER_GET_OFFSET(now) 
     138                ); 
     139            debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: TSS=%011lu, SEC=%03u CY=%04u OFF=%04u\n", 
     140                cycle, test_ts, TICKS_TO_SECS(test_ts), TICKS_TO_CYCLES(test_ts), TICKS_TO_OFFSET(test_ts) 
     141                ); 
     142                 
     143            int64_t diff_ts = diffTicks(now_ticks, test_ts); 
     144            debugOutput(DEBUG_LEVEL_VERBOSE, "DIFF  : TCK=%011lld, SEC=%03llu CY=%04llu OFF=%04llu\n", 
     145                diff_ts,  
     146                TICKS_TO_SECS((uint64_t)diff_ts), 
     147                TICKS_TO_CYCLES((uint64_t)diff_ts), 
     148                TICKS_TO_OFFSET((uint64_t)diff_ts) 
     149                ); 
     150        } 
     151        m_last_syt = ntohs(packet->syt); 
     152        m_last_now = nowX; 
     153        m_last_good_cycle = cycle; 
     154        m_last_dropped = dropped_cycles; 
    961155 
    962156        debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "RECV: CY=%04u TS=%011llu\n", 
     
    977171            debugOutput(DEBUG_LEVEL_VERBOSE,"Receive StreamProcessor %p started running at %d\n", this, cycle); 
    978172            m_running=true; 
    979         } 
    980  
     173            m_data_buffer->setBufferTailTimestamp(m_last_timestamp); 
     174            // we don't want this first sample to be written 
     175            return RAW1394_ISO_OK; 
     176        } 
     177 
     178        // if we are not running yet, there is nothing more to do 
     179        if(!m_running) { 
     180            return RAW1394_ISO_OK; 
     181        } 
    981182        #ifdef DEBUG_OFF 
    982183        if((cycle % 1000) == 0) { 
     
    1008209        //=> process the packet 
    1009210        // add the data payload to the ringbuffer 
     211         
     212        if(dropped_cycles) { 
     213            debugWarning("(%p) Correcting timestamp for dropped cycles, discarding packet...\n", this); 
     214            m_data_buffer->setBufferTailTimestamp(m_last_timestamp); 
     215            // we don't want this first sample to be written 
     216            return RAW1394_ISO_OK; 
     217        } 
     218         
    1010219        if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) { 
    1011220            retval=RAW1394_ISO_OK; 
     
    1105314 
    1106315    assert(m_data_buffer); 
    1107     m_data_buffer->setBufferSize(ringbuffer_size_frames); 
     316    m_data_buffer->setBufferSize(ringbuffer_size_frames * 2); 
    1108317    m_data_buffer->setEventSize(sizeof(quadlet_t)); 
    1109318    m_data_buffer->setEventsPerFrame(m_dimension); 
     
    1214423    m_PeriodStat.mark(m_data_buffer->getBufferFill()); 
    1215424 
     425#ifdef DEBUG 
     426    uint64_t ts_head; 
     427    signed int fc; 
     428    int32_t lag_ticks; 
     429    float lag_frames; 
     430 
     431    // in order to sync up multiple received streams, we should  
     432    // use the ts parameter. It specifies the time of the block's  
     433    // first sample. 
     434     
     435    ffado_timestamp_t ts_head_tmp; 
     436    m_data_buffer->getBufferHeadTimestamp(&ts_head_tmp, &fc); 
     437    ts_head=(uint64_t)ts_head_tmp; 
     438    lag_ticks=diffTicks(ts, ts_head); 
     439    float rate=m_data_buffer->getRate(); 
     440     
     441    assert(rate!=0.0); 
     442     
     443    lag_frames=(((float)lag_ticks)/rate); 
     444     
     445    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): drifts %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n", 
     446                 this, lag_ticks, lag_frames,rate, ts, ts_head, fc); 
     447 
     448    if (lag_frames>=1.0) { 
     449        // the stream lags 
     450        debugWarning( "stream (%p): lags  with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n", 
     451                      this, lag_ticks, lag_frames,rate, ts, ts_head, fc); 
     452    } else if (lag_frames<=-1.0) { 
     453        // the stream leads 
     454        debugWarning( "stream (%p): leads with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n", 
     455                      this, lag_ticks, lag_frames,rate, ts, ts_head, fc); 
     456    } 
     457#endif 
    1216458    // ask the buffer to process nbframes of frames 
    1217459    // using it's registered client's processReadBlock(), 
  • branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.h

    r709 r712  
    2222 */ 
    2323 
    24 #ifndef __FFADO_AMDTPSTREAMPROCESSOR__ 
    25 #define __FFADO_AMDTPSTREAMPROCESSOR__ 
     24#ifndef __FFADO_AMDTPRECEIVESTREAMPROCESSOR__ 
     25#define __FFADO_AMDTPRECEIVESTREAMPROCESSOR__ 
    2626 
    2727/** 
     
    5757class AmdtpAudioPort; 
    5858class AmdtpMidiPort; 
    59 class AmdtpReceiveStreamProcessor; 
    60  
    61 /*! 
    62 \brief The Base Class for an AMDTP transmit stream processor 
    63  
    64  This class implements a TransmitStreamProcessor that multiplexes Ports 
    65  into AMDTP streams. 
    66  
    67 */ 
    68 class AmdtpTransmitStreamProcessor 
    69     : public TransmitStreamProcessor 
    70 { 
    71  
    72 public: 
    73     /** 
    74      * Create a AMDTP transmit StreamProcessor 
    75      * @param port 1394 port 
    76      * @param framerate frame rate 
    77      * @param dimension number of substreams in the ISO stream 
    78      *                  (midi-muxed is only one stream) 
    79      */ 
    80     AmdtpTransmitStreamProcessor(int port, int framerate, int dimension); 
    81     virtual ~AmdtpTransmitStreamProcessor() {}; 
    82  
    83     enum raw1394_iso_disposition 
    84             getPacket(unsigned char *data, unsigned int *length, 
    85                     unsigned char *tag, unsigned char *sy, 
    86                     int cycle, unsigned int dropped, unsigned int max_length); 
    87  
    88     bool init(); 
    89     bool reset(); 
    90     bool prepare(); 
    91  
    92     bool prepareForStop(); 
    93     bool prepareForStart(); 
    94  
    95     bool prepareForEnable(uint64_t time_to_enable_at); 
    96  
    97     bool putFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents from the client 
    98     bool putFramesDry(unsigned int nbframes, int64_t ts); 
    99  
    100     // We have 1 period of samples = m_period 
    101     // this period takes m_period/m_framerate seconds of time 
    102     // during this time, 8000 packets are sent 
    103 //     unsigned int getPacketsPerPeriod() {return (m_period*8000)/m_framerate;}; 
    104  
    105     // however, if we only count the number of used packets 
    106     // it is m_period / m_syt_interval 
    107     unsigned int getPacketsPerPeriod() {return (m_period)/m_syt_interval;}; 
    108  
    109     unsigned int getMaxPacketSize() {return 4 * (2 + m_syt_interval * m_dimension);}; 
    110  
    111 protected: 
    112     bool processWriteBlock(char *data, unsigned int nevents, unsigned int offset); 
    113  
    114     struct iec61883_cip m_cip_status; 
    115  
    116     int m_dimension; 
    117     unsigned int m_syt_interval; 
    118  
    119     int m_fdf; 
    120  
    121     bool prefill(); 
    122  
    123     unsigned int fillNoDataPacketHeader(struct iec61883_packet *packet, unsigned int* length); 
    124     unsigned int fillDataPacketHeader(struct iec61883_packet *packet, unsigned int* length, uint32_t ts); 
    125  
    126  
    127     bool transferSilence(unsigned int size); 
    128  
    129     int transmitBlock(char *data, unsigned int nevents, 
    130                         unsigned int offset); 
    131  
    132     bool encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc); 
    133     int encodePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, 
    134                                 unsigned int offset, unsigned int nevents); 
    135  
    136     int transmitSilenceBlock(char *data, unsigned int nevents, 
    137                         unsigned int offset); 
    138     int encodeSilencePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, 
    139                                 unsigned int offset, unsigned int nevents); 
    140     void updatePreparedState(); 
    141  
    142     unsigned long m_last_timestamp; 
    143  
    144     unsigned int m_dbc; 
    145  
    146     unsigned int m_ringbuffer_size_frames; 
    147 }; 
    14859/*! 
    14960\brief The Base Class for an AMDTP receive stream processor 
     
    207118    unsigned int m_syt_interval; 
    208119 
     120    uint64_t m_dropped; /// FIXME:debug 
     121    uint64_t m_last_dropped; /// FIXME:debug 
     122    uint64_t m_last_syt; /// FIXME:debug 
     123    uint64_t m_last_now; /// FIXME:debug 
     124    int m_last_good_cycle; /// FIXME:debug 
    209125    uint64_t m_last_timestamp; /// last timestamp (in ticks) 
    210126    uint64_t m_last_timestamp2; /// last timestamp (in ticks) 
     
    215131} // end of namespace Streaming 
    216132 
    217 #endif /* __FFADO_AMDTPSTREAMPROCESSOR__ */ 
     133#endif /* __FFADO_AMDTPRECEIVESTREAMPROCESSOR__ */ 
    218134 
  • branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpSlaveStreamProcessor.h

    r705 r712  
    2828 * This class implements IEC61883-6 / AM824 / AMDTP based streaming 
    2929 */ 
    30 #include "AmdtpStreamProcessor.h" 
     30#include "AmdtpReceiveStreamProcessor.h" 
     31#include "AmdtpTransmitStreamProcessor.h" 
    3132#include "../util/cip.h" 
    3233 
  • branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp

    r709 r712  
    2222 */ 
    2323 
    24 #include "AmdtpStreamProcessor.h" 
     24#include "AmdtpTransmitStreamProcessor.h" 
    2525#include "AmdtpPort.h" 
    2626 
     
    7878    debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,"Xmit handler for cycle %d, (running=%d)\n", 
    7979        cycle, m_running); 
     80 
     81    if (addCycles(m_last_cycle, 1) != cycle) { 
     82        debugWarning("(%p) Dropped %d packets on cycle %d\n", diffCycles(cycle,m_last_cycle)-1, cycle); 
     83    } 
    8084 
    8185    m_last_cycle=cycle; 
     
    159163    // given by TRANSMIT_TRANSFER_DELAY (in ticks), but we can send 
    160164    // packets early if we want to. (not completely according to spec) 
    161     const int max_cycles_to_transmit_early = 1
     165    const int max_cycles_to_transmit_early = 5
    162166 
    163167    if( !m_running || !m_data_buffer->isEnabled() ) { 
     
    487491 
    488492    assert(m_data_buffer); 
    489     m_data_buffer->setBufferSize(m_ringbuffer_size_frames); 
     493    m_data_buffer->setBufferSize(m_ringbuffer_size_frames * 2); 
    490494    m_data_buffer->setEventSize(sizeof(quadlet_t)); 
    491495    m_data_buffer->setEventsPerFrame(m_dimension); 
     
    622626bool AmdtpTransmitStreamProcessor::transferSilence(unsigned int nframes) { 
    623627    bool retval; 
    624  
     628    signed int fc; 
     629    ffado_timestamp_t ts_tail_tmp; 
     630    uint64_t ts_tail; 
     631     
     632    // prepare a buffer of silence 
    625633    char *dummybuffer=(char *)calloc(sizeof(quadlet_t),nframes*m_dimension); 
    626  
    627634    transmitSilenceBlock(dummybuffer, nframes, 0); 
    628635 
     636     
     637    m_data_buffer->getBufferTailTimestamp(&ts_tail_tmp, &fc); 
     638    if (fc != 0) { 
     639        debugWarning("Prefilling a buffer that already contains %d frames\n", fc); 
     640    } 
     641 
     642    ts_tail = (uint64_t)ts_tail_tmp; 
     643    // modify the timestamp such that it makes sense 
     644    ts_tail = addTicks(ts_tail, (uint64_t)(nframes * getTicksPerFrame())); 
    629645    // add the silence data to the ringbuffer 
    630     if(m_data_buffer->writeFrames(nframes, dummybuffer, 0)) { 
     646    if(m_data_buffer->writeFrames(nframes, dummybuffer, ts_tail)) { 
    631647        retval=true; 
    632648    } else { 
     
    664680        retval=true; 
    665681    } else { 
    666         debugWarning("Could not write to event buffer\n"); 
     682        debugWarning("Could not write %u events to event buffer\n", nbframes); 
    667683        retval=false; 
    668684    } 
     
    894910} 
    895911 
    896 /* --------------------- RECEIVE ----------------------- */ 
    897  
    898 AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int port, int framerate, int dimension) 
    899     : ReceiveStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0), m_last_timestamp2(0)  
    900 {} 
    901  
    902 bool AmdtpReceiveStreamProcessor::init() { 
    903  
    904     // call the parent init 
    905     // this has to be done before allocating the buffers, 
    906     // because this sets the buffersizes from the processormanager 
    907     if(!ReceiveStreamProcessor::init()) { 
    908         debugFatal("Could not do base class init (%d)\n",this); 
    909         return false; 
    910     } 
    911     return true; 
    912 } 
    913  
    914 enum raw1394_iso_disposition 
    915 AmdtpReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length, 
    916                   unsigned char channel, unsigned char tag, unsigned char sy, 
    917                   unsigned int cycle, unsigned int dropped) { 
    918  
    919     enum raw1394_iso_disposition retval=RAW1394_ISO_OK; 
    920     m_last_cycle=cycle; 
    921  
    922     struct iec61883_packet *packet = (struct iec61883_packet *) data; 
    923     assert(packet); 
    924  
    925 #ifdef DEBUG 
    926     if(dropped>0) { 
    927         debugWarning("Dropped %d packets on cycle %d\n",dropped, cycle); 
    928     } 
    929  
    930     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"ch%2u: CY=%4u, SYT=%08X (%4ucy + %04uticks) (running=%d)\n", 
    931         channel, cycle, ntohs(packet->syt), 
    932         CYCLE_TIMER_GET_CYCLES(ntohs(packet->syt)), CYCLE_TIMER_GET_OFFSET(ntohs(packet->syt)), 
    933         m_running); 
    934  
    935     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, 
    936         "RCV: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d\n", 
    937         channel, packet->fdf, 
    938         packet->syt, 
    939         packet->dbs, 
    940         packet->dbc, 
    941         packet->fmt, 
    942         length); 
    943  
    944 #endif 
    945  
    946     // check if this is a valid packet 
    947     if((packet->syt != 0xFFFF) 
    948        && (packet->fdf != 0xFF) 
    949        && (packet->fmt == 0x10) 
    950        && (packet->dbs>0) 
    951        && (length>=2*sizeof(quadlet_t))) { 
    952  
    953         unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs; 
    954  
    955         //=> store the previous timestamp 
    956         m_last_timestamp2=m_last_timestamp; 
    957  
    958         //=> convert the SYT to a full timestamp in ticks 
    959         m_last_timestamp=sytRecvToFullTicks((uint32_t)ntohs(packet->syt), 
    960                                         cycle, m_handler->getCycleTimer()); 
    961  
    962         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "RECV: CY=%04u TS=%011llu\n", 
    963                 cycle, m_last_timestamp); 
    964  
    965         // we have to keep in mind that there are also 
    966         // some packets buffered by the ISO layer, 
    967         // at most x=m_handler->getWakeupInterval() 
    968         // these contain at most x*syt_interval 
    969         // frames, meaning that we might receive 
    970         // this packet x*syt_interval*ticks_per_frame 
    971         // later than expected (the real receive time) 
    972         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"STMP: %lluticks | buff=%d, syt_interval=%d, tpf=%f\n", 
    973             m_last_timestamp, m_handler->getWakeupInterval(),m_syt_interval,getTicksPerFrame()); 
    974  
    975         //=> signal that we're running (if we are) 
    976         if(!m_running && nevents && m_last_timestamp2 && m_last_timestamp) { 
    977             debugOutput(DEBUG_LEVEL_VERBOSE,"Receive StreamProcessor %p started running at %d\n", this, cycle); 
    978             m_running=true; 
    979         } 
    980  
    981         #ifdef DEBUG_OFF 
    982         if((cycle % 1000) == 0) { 
    983             uint32_t now=m_handler->getCycleTimer(); 
    984             uint32_t syt = (uint32_t)ntohs(packet->syt); 
    985             uint32_t now_ticks=CYCLE_TIMER_TO_TICKS(now); 
    986  
    987             uint32_t test_ts=sytRecvToFullTicks(syt, cycle, now); 
    988  
    989             debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: SYT=%08X,            CY=%02d OFF=%04d\n", 
    990                 cycle, syt, CYCLE_TIMER_GET_CYCLES(syt), CYCLE_TIMER_GET_OFFSET(syt) 
    991                 ); 
    992             debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: NOW=%011lu, SEC=%03u CY=%02u OFF=%04u\n", 
    993                 cycle, now_ticks, CYCLE_TIMER_GET_SECS(now), CYCLE_TIMER_GET_CYCLES(now), CYCLE_TIMER_GET_OFFSET(now) 
    994                 ); 
    995             debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: TSS=%011lu, SEC=%03u CY=%02u OFF=%04u\n", 
    996                 cycle, test_ts, TICKS_TO_SECS(test_ts), TICKS_TO_CYCLES(test_ts), TICKS_TO_OFFSET(test_ts) 
    997                 ); 
    998         } 
    999         #endif 
    1000  
    1001         #ifdef DEBUG 
    1002             // keep track of the lag 
    1003             uint32_t now=m_handler->getCycleTimer(); 
    1004             int32_t diff = diffCycles( cycle,  ((int)CYCLE_TIMER_GET_CYCLES(now)) ); 
    1005             m_PacketStat.mark(diff); 
    1006         #endif 
    1007  
    1008         //=> process the packet 
    1009         // add the data payload to the ringbuffer 
    1010         if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) { 
    1011             retval=RAW1394_ISO_OK; 
    1012  
    1013             // process all ports that should be handled on a per-packet base 
    1014             // this is MIDI for AMDTP (due to the need of DBC) 
    1015             if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) { 
    1016                 debugWarning("Problem decoding Packet Ports\n"); 
    1017                 retval=RAW1394_ISO_DEFER; 
    1018             } 
    1019  
    1020         } else { 
    1021  
    1022 //             debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n", 
    1023 //                  cycle, m_data_buffer->getFrameCounter(), m_handler->getPacketCount()); 
    1024  
    1025             m_xruns++; 
    1026  
    1027             retval=RAW1394_ISO_DEFER; 
    1028         } 
    1029     } 
    1030  
    1031     return retval; 
    1032 } 
    1033  
    1034 void AmdtpReceiveStreamProcessor::dumpInfo() { 
    1035     StreamProcessor::dumpInfo(); 
    1036 } 
    1037  
    1038 bool AmdtpReceiveStreamProcessor::reset() { 
    1039  
    1040     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n"); 
    1041  
    1042     m_PeriodStat.reset(); 
    1043     m_PacketStat.reset(); 
    1044     m_WakeupStat.reset(); 
    1045  
    1046     m_data_buffer->setTickOffset(0); 
    1047  
    1048     // reset all non-device specific stuff 
    1049     // i.e. the iso stream and the associated ports 
    1050     if(!ReceiveStreamProcessor::reset()) { 
    1051             debugFatal("Could not do base class reset\n"); 
    1052             return false; 
    1053     } 
    1054     return true; 
    1055 } 
    1056  
    1057 bool AmdtpReceiveStreamProcessor::prepare() { 
    1058  
    1059     m_PeriodStat.setName("RCV PERIOD"); 
    1060     m_PacketStat.setName("RCV PACKET"); 
    1061     m_WakeupStat.setName("RCV WAKEUP"); 
    1062  
    1063     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this); 
    1064  
    1065     // prepare all non-device specific stuff 
    1066     // i.e. the iso stream and the associated ports 
    1067     if(!ReceiveStreamProcessor::prepare()) { 
    1068         debugFatal("Could not prepare base class\n"); 
    1069         return false; 
    1070     } 
    1071  
    1072     switch (m_framerate) { 
    1073     case 32000: 
    1074         m_syt_interval = 8; 
    1075         break; 
    1076     case 44100: 
    1077         m_syt_interval = 8; 
    1078         break; 
    1079     default: 
    1080     case 48000: 
    1081         m_syt_interval = 8; 
    1082         break; 
    1083     case 88200: 
    1084         m_syt_interval = 16; 
    1085         break; 
    1086     case 96000: 
    1087         m_syt_interval = 16; 
    1088         break; 
    1089     case 176400: 
    1090         m_syt_interval = 32; 
    1091         break; 
    1092     case 192000: 
    1093         m_syt_interval = 32; 
    1094         break; 
    1095     } 
    1096  
    1097     // prepare the framerate estimate 
    1098     float ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate); 
    1099     m_ticks_per_frame=ticks_per_frame; 
    1100  
    1101     debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n",ticks_per_frame); 
    1102  
    1103     // initialize internal buffer 
    1104     unsigned int ringbuffer_size_frames=m_nb_buffers * m_period; 
    1105  
    1106     assert(m_data_buffer); 
    1107     m_data_buffer->setBufferSize(ringbuffer_size_frames); 
    1108     m_data_buffer->setEventSize(sizeof(quadlet_t)); 
    1109     m_data_buffer->setEventsPerFrame(m_dimension); 
    1110  
    1111     // the buffer is written every syt_interval 
    1112     m_data_buffer->setUpdatePeriod(m_syt_interval); 
    1113     m_data_buffer->setNominalRate(ticks_per_frame); 
    1114  
    1115     m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND); 
    1116  
    1117     m_data_buffer->prepare(); 
    1118  
    1119     // set the parameters of ports we can: 
    1120     // we want the audio ports to be period buffered, 
    1121     // and the midi ports to be packet buffered 
    1122     for ( PortVectorIterator it = m_Ports.begin(); 
    1123           it != m_Ports.end(); 
    1124           ++it ) 
    1125     { 
    1126         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
    1127         if(!(*it)->setBufferSize(m_period)) { 
    1128             debugFatal("Could not set buffer size to %d\n",m_period); 
    1129             return false; 
    1130         } 
    1131  
    1132         switch ((*it)->getPortType()) { 
    1133             case Port::E_Audio: 
    1134                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) { 
    1135                     debugFatal("Could not set signal type to PeriodSignalling"); 
    1136                     return false; 
    1137                 } 
    1138                 // buffertype and datatype are dependant on the API 
    1139                 debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n"); 
    1140                 // buffertype and datatype are dependant on the API 
    1141                 if(!(*it)->setBufferType(Port::E_PointerBuffer)) { 
    1142                     debugFatal("Could not set buffer type"); 
    1143                     return false; 
    1144                 } 
    1145                 if(!(*it)->useExternalBuffer(true)) { 
    1146                     debugFatal("Could not set external buffer usage"); 
    1147                     return false; 
    1148                 } 
    1149                 if(!(*it)->setDataType(Port::E_Float)) { 
    1150                     debugFatal("Could not set data type"); 
    1151                     return false; 
    1152                 } 
    1153                 break; 
    1154             case Port::E_Midi: 
    1155                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) { 
    1156                     debugFatal("Could not set signal type to PacketSignalling"); 
    1157                     return false; 
    1158                 } 
    1159                 // buffertype and datatype are dependant on the API 
    1160                 // buffertype and datatype are dependant on the API 
    1161                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); 
    1162                 // buffertype and datatype are dependant on the API 
    1163                 if(!(*it)->setBufferType(Port::E_RingBuffer)) { 
    1164                     debugFatal("Could not set buffer type"); 
    1165                     return false; 
    1166                 } 
    1167                 if(!(*it)->setDataType(Port::E_MidiEvent)) { 
    1168                     debugFatal("Could not set data type"); 
    1169                     return false; 
    1170                 } 
    1171                 break; 
    1172             default: 
    1173                 debugWarning("Unsupported port type specified\n"); 
    1174                 break; 
    1175         } 
    1176     } 
    1177  
    1178     // the API specific settings of the ports should already be set, 
    1179     // as this is called from the processorManager->prepare() 
    1180     // so we can init the ports 
    1181     if(!initPorts()) { 
    1182         debugFatal("Could not initialize ports!\n"); 
    1183         return false; 
    1184     } 
    1185  
    1186     if(!preparePorts()) { 
    1187         debugFatal("Could not initialize ports!\n"); 
    1188         return false; 
    1189     } 
    1190  
    1191     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n"); 
    1192     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, DBS: %d, SYT: %d\n", 
    1193              m_framerate,m_dimension,m_syt_interval); 
    1194     debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n", 
    1195              m_period,m_nb_buffers); 
    1196     debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n", 
    1197              m_port,m_channel); 
    1198  
    1199     return true; 
    1200  
    1201 } 
    1202  
    1203 bool AmdtpReceiveStreamProcessor::prepareForStart() { 
    1204     disable(); 
    1205     return true; 
    1206 } 
    1207  
    1208 bool AmdtpReceiveStreamProcessor::prepareForStop() { 
    1209     disable(); 
    1210     return true; 
    1211 } 
    1212  
    1213 bool AmdtpReceiveStreamProcessor::getFrames(unsigned int nbframes, int64_t ts) { 
    1214     m_PeriodStat.mark(m_data_buffer->getBufferFill()); 
    1215  
    1216     // ask the buffer to process nbframes of frames 
    1217     // using it's registered client's processReadBlock(), 
    1218     // which should be ours 
    1219     m_data_buffer->blockProcessReadFrames(nbframes); 
    1220  
    1221     return true; 
    1222 } 
    1223  
    1224 bool AmdtpReceiveStreamProcessor::getFramesDry(unsigned int nbframes, int64_t ts) { 
    1225     m_PeriodStat.mark(m_data_buffer->getBufferFill()); 
    1226     int frames_to_ditch=(int)(nbframes); 
    1227     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): dry run %d frames (@ ts=%lld)\n", 
    1228                  this, frames_to_ditch, ts); 
    1229     char dummy[m_data_buffer->getBytesPerFrame()]; // one frame of garbage 
    1230  
    1231     while (frames_to_ditch--) { 
    1232         m_data_buffer->readFrames(1, dummy); 
    1233     } 
    1234     return true; 
    1235 } 
    1236  
    1237 /** 
    1238  * \brief write received events to the stream ringbuffers. 
    1239  */ 
    1240 bool AmdtpReceiveStreamProcessor::processReadBlock(char *data, 
    1241                        unsigned int nevents, unsigned int offset) 
    1242 { 
    1243     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "(%p)->processReadBlock(%u, %u)\n",this,nevents,offset); 
    1244  
    1245     bool no_problem=true; 
    1246  
    1247     for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    1248           it != m_PeriodPorts.end(); 
    1249           ++it ) 
    1250     { 
    1251  
    1252         if((*it)->isDisabled()) {continue;}; 
    1253  
    1254         //FIXME: make this into a static_cast when not DEBUG? 
    1255  
    1256         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    1257         assert(pinfo); // this should not fail!! 
    1258  
    1259         switch(pinfo->getFormat()) { 
    1260         case AmdtpPortInfo::E_MBLA: 
    1261             if(decodeMBLAEventsToPort(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    1262                 debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str()); 
    1263                 no_problem=false; 
    1264             } 
    1265             break; 
    1266         case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    1267             break; 
    1268     /* for this processor, midi is a packet based port 
    1269         case AmdtpPortInfo::E_Midi: 
    1270             break;*/ 
    1271         default: // ignore 
    1272             break; 
    1273         } 
    1274     } 
    1275     return no_problem; 
    1276  
    1277 } 
    1278  
    1279 /** 
    1280  * @brief decode a packet for the packet-based ports 
    1281  * 
    1282  * @param data Packet data 
    1283  * @param nevents number of events in data (including events of other ports & port types) 
    1284  * @param dbc DataBlockCount value for this packet 
    1285  * @return true if all successfull 
    1286  */ 
    1287 bool AmdtpReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc) 
    1288 { 
    1289     bool ok=true; 
    1290  
    1291     quadlet_t *target_event=NULL; 
    1292     unsigned int j; 
    1293  
    1294     for ( PortVectorIterator it = m_PacketPorts.begin(); 
    1295           it != m_PacketPorts.end(); 
    1296           ++it ) 
    1297     { 
    1298  
    1299 #ifdef DEBUG 
    1300         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    1301         assert(pinfo); // this should not fail!! 
    1302  
    1303         // the only packet type of events for AMDTP is MIDI in mbla 
    1304         assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi); 
    1305 #endif 
    1306         AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it); 
    1307  
    1308         // we decode this directly (no function call) due to the high frequency 
    1309         /* idea: 
    1310         spec says: current_midi_port=(dbc+j)%8; 
    1311         => if we start at (dbc+stream->location-1)%8, 
    1312         we'll start at the right event for the midi port. 
    1313         => if we increment j with 8, we stay at the right event. 
    1314         */ 
    1315         // FIXME: as we know in advance how big a packet is (syt_interval) we can 
    1316         //        predict how much loops will be present here 
    1317         for(j = (dbc & 0x07)+mp->getLocation(); j < nevents; j += 8) { 
    1318             target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); 
    1319             quadlet_t sample_int=ntohl(*target_event); 
    1320             // FIXME: this assumes that 2X and 3X speed isn't used, 
    1321             // because only the 1X slot is put into the ringbuffer 
    1322             if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) { 
    1323                 sample_int=(sample_int >> 16) & 0x000000FF; 
    1324                 if(!mp->writeEvent(&sample_int)) { 
    1325                     debugWarning("Packet port events lost\n"); 
    1326                     ok=false; 
    1327                 } 
    1328             } 
    1329         } 
    1330  
    1331     } 
    1332  
    1333     return ok; 
    1334 } 
    1335  
    1336 int AmdtpReceiveStreamProcessor::decodeMBLAEventsToPort(AmdtpAudioPort *p, quadlet_t *data, 
    1337                        unsigned int offset, unsigned int nevents) 
    1338 { 
    1339     unsigned int j=0; 
    1340  
    1341 //     printf("****************\n"); 
    1342 //     hexDumpQuadlets(data,m_dimension*4); 
    1343 //     printf("****************\n"); 
    1344  
    1345     quadlet_t *target_event; 
    1346  
    1347     target_event=(quadlet_t *)(data + p->getPosition()); 
    1348  
    1349     switch(p->getDataType()) { 
    1350         default: 
    1351         case Port::E_Int24: 
    1352             { 
    1353                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
    1354  
    1355                 assert(nevents + offset <= p->getBufferSize()); 
    1356  
    1357                 buffer+=offset; 
    1358  
    1359                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    1360                     *(buffer)=(ntohl((*target_event) ) & 0x00FFFFFF); 
    1361                     buffer++; 
    1362                     target_event+=m_dimension; 
    1363                 } 
    1364             } 
    1365             break; 
    1366         case Port::E_Float: 
    1367             { 
    1368                 const float multiplier = 1.0f / (float)(0x7FFFFF); 
    1369                 float *buffer=(float *)(p->getBufferAddress()); 
    1370  
    1371                 assert(nevents + offset <= p->getBufferSize()); 
    1372  
    1373                 buffer+=offset; 
    1374  
    1375                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    1376  
    1377                     unsigned int v = ntohl(*target_event) & 0x00FFFFFF; 
    1378                     // sign-extend highest bit of 24-bit int 
    1379                     int tmp = (int)(v << 8) / 256; 
    1380  
    1381                     *buffer = tmp * multiplier; 
    1382  
    1383                     buffer++; 
    1384                     target_event+=m_dimension; 
    1385                 } 
    1386             } 
    1387             break; 
    1388     } 
    1389  
    1390     return 0; 
    1391 } 
    1392  
    1393912} // end of namespace Streaming 
  • branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h

    r709 r712  
    2222 */ 
    2323 
    24 #ifndef __FFADO_AMDTPSTREAMPROCESSOR__ 
    25 #define __FFADO_AMDTPSTREAMPROCESSOR__ 
     24#ifndef __FFADO_AMDTPTRANSMITSTREAMPROCESSOR__ 
     25#define __FFADO_AMDTPTRANSMITSTREAMPROCESSOR__ 
    2626 
    2727/** 
     
    5757class AmdtpAudioPort; 
    5858class AmdtpMidiPort; 
    59 class AmdtpReceiveStreamProcessor; 
    6059 
    6160/*! 
     
    146145    unsigned int m_ringbuffer_size_frames; 
    147146}; 
    148 /*! 
    149 \brief The Base Class for an AMDTP receive stream processor 
    150  
    151  This class implements a ReceiveStreamProcessor that demultiplexes 
    152  AMDTP streams into Ports. 
    153  
    154 */ 
    155 class AmdtpReceiveStreamProcessor 
    156     : public ReceiveStreamProcessor 
    157 { 
    158  
    159 public: 
    160     /** 
    161      * Create a AMDTP receive StreamProcessor 
    162      * @param port 1394 port 
    163      * @param framerate frame rate 
    164      * @param dimension number of substreams in the ISO stream 
    165      *                  (midi-muxed is only one stream) 
    166      */ 
    167     AmdtpReceiveStreamProcessor(int port, int framerate, int dimension); 
    168     virtual ~AmdtpReceiveStreamProcessor() {}; 
    169  
    170     enum raw1394_iso_disposition putPacket(unsigned char *data, unsigned int length, 
    171                   unsigned char channel, unsigned char tag, unsigned char sy, 
    172                   unsigned int cycle, unsigned int dropped); 
    173  
    174  
    175     bool init(); 
    176     bool reset(); 
    177     bool prepare(); 
    178  
    179     bool prepareForStop(); 
    180     bool prepareForStart(); 
    181  
    182     bool getFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents to the client 
    183     bool getFramesDry(unsigned int nbframes, int64_t ts); 
    184  
    185     // We have 1 period of samples = m_period 
    186     // this period takes m_period/m_framerate seconds of time 
    187     // during this time, 8000 packets are sent 
    188 //     unsigned int getPacketsPerPeriod() {return (m_period*8000)/m_framerate;}; 
    189  
    190     // however, if we only count the number of used packets 
    191     // it is m_period / m_syt_interval 
    192     unsigned int getPacketsPerPeriod() {return (m_period)/m_syt_interval;}; 
    193  
    194     unsigned int getMaxPacketSize() {return 4 * (2 + m_syt_interval * m_dimension);}; 
    195  
    196     void dumpInfo(); 
    197 protected: 
    198  
    199     bool processReadBlock(char *data, unsigned int nevents, unsigned int offset); 
    200  
    201     bool decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc); 
    202  
    203     int decodeMBLAEventsToPort(AmdtpAudioPort *, quadlet_t *data, unsigned int offset, unsigned int nevents); 
    204     void updatePreparedState(); 
    205  
    206     int m_dimension; 
    207     unsigned int m_syt_interval; 
    208  
    209     uint64_t m_last_timestamp; /// last timestamp (in ticks) 
    210     uint64_t m_last_timestamp2; /// last timestamp (in ticks) 
    211     uint64_t m_last_timestamp_at_period_ticks; 
    212 }; 
    213  
    214147 
    215148} // end of namespace Streaming 
    216149 
    217 #endif /* __FFADO_AMDTPSTREAMPROCESSOR__ */ 
     150#endif /* __FFADO_AMDTPTRANSMITSTREAMPROCESSOR__ */ 
    218151 
  • branches/ppalmers-streaming/src/libstreaming/generic/StreamProcessor.cpp

    r709 r712  
    300300    IsoStream::setVerboseLevel(l); 
    301301    PortManager::setVerboseLevel(l); 
     302    m_data_buffer->setVerboseLevel(l); 
    302303} 
    303304 
  • branches/ppalmers-streaming/src/libstreaming/generic/StreamProcessor.h

    r709 r712  
    107107    virtual bool prepareForStart() {return true;}; 
    108108 
    109  
    110109public: 
    111110    Util::TimestampedBuffer *m_data_buffer; 
     
    234233 
    235234        int getLastCycle() {return m_last_cycle;}; 
     235        int getFrameRate() {return m_framerate;}; 
    236236 
    237237        int getBufferFill(); 
  • branches/ppalmers-streaming/src/libstreaming/StreamProcessorManager.cpp

    r709 r712  
    341341    m_SyncSource->setSyncDelay(max_of_min_delay); 
    342342 
    343  
     343    debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for device to indicate clock sync lock...\n"); 
     344    //sleep(2); // FIXME: be smarter here 
     345     
    344346    debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting StreamProcessors...\n"); 
    345347    // now we reset the frame counters 
     
    365367//     m_SyncSource->m_data_buffer->setTransparent(false); 
    366368//     debugShowBackLog(); 
     369 
     370//     m_SyncSource->setVerboseLevel(DEBUG_LEVEL_ULTRA_VERBOSE); 
    367371     
    368372    debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for sync...\n"); 
    369373    // in order to obtain that, we wait for the first periods to be 
    370374    // received. 
    371     int nb_sync_runs=10; 
     375    int nb_sync_runs=20; 
    372376    while(nb_sync_runs--) { // or while not sync-ed? 
    373377        waitForPeriod(); 
    374  
    375378        // drop the frames for all receive SP's 
    376379        dryRun(StreamProcessor::E_Receive); 
     
    378381        // we don't have to dryrun for the xmit SP's since they 
    379382        // are not sending data yet. 
    380     } 
     383         
     384        // sync the xmit SP's buffer head timestamps 
     385        for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
     386                it != m_TransmitProcessors.end(); 
     387                ++it ) { 
     388            // FIXME: encapsulate 
     389            (*it)->m_data_buffer->setBufferHeadTimestamp(m_time_of_transfer); 
     390        } 
     391    } 
     392//     m_SyncSource->setVerboseLevel(DEBUG_LEVEL_VERBOSE); 
    381393 
    382394    debugOutput( DEBUG_LEVEL_VERBOSE, " sync at TS=%011llu (%03us %04uc %04ut)...\n",  
     
    433445 
    434446    debugOutput( DEBUG_LEVEL_VERBOSE, "Running dry for a while...\n"); 
    435     #define MAX_DRYRUN_CYCLES               2
     447    #define MAX_DRYRUN_CYCLES               4
    436448    #define MIN_SUCCESSFUL_DRYRUN_CYCLES    4 
    437449    // run some cycles 'dry' such that everything can stabilize 
     
    442454 
    443455        waitForPeriod(); 
     456 
     457        if (dryRun()) { 
     458            nb_succesful_cycles++; 
     459        } else { 
     460            debugOutput( DEBUG_LEVEL_VERBOSE, " This dry-run was not xrun free...\n" ); 
     461            resetXrunCounters(); 
     462            // reset the transmit SP's such that there is no issue with accumulating buffers 
     463            // FIXME: what about receive SP's 
     464            for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 
     465                    it != m_TransmitProcessors.end(); 
     466                    ++it ) { 
     467                // FIXME: encapsulate 
     468                (*it)->reset(); //CHECK!!! 
     469                (*it)->m_data_buffer->setBufferHeadTimestamp(m_time_of_transfer); 
     470            } 
     471             
     472            nb_succesful_cycles = 0; 
     473            // FIXME: xruns can screw up the framecounter accounting. do something more sane here 
     474        } 
     475        nb_dryrun_cycles_left--; 
     476    } 
     477 
     478    if(nb_dryrun_cycles_left == 0) { 
     479        debugOutput( DEBUG_LEVEL_VERBOSE, " max # dry-run cycles achieved without steady-state...\n" ); 
     480        return false; 
     481    } 
     482    debugOutput( DEBUG_LEVEL_VERBOSE, " dry-run resulted in steady-state...\n" ); 
     483 
     484    // now we should clear the xrun flags 
     485    resetXrunCounters(); 
     486 
     487/*    debugOutput( DEBUG_LEVEL_VERBOSE, "Aligning streams...\n"); 
     488    // run some cycles 'dry' such that everything can stabilize 
     489    nb_dryrun_cycles_left = MAX_DRYRUN_CYCLES; 
     490    nb_succesful_cycles = 0; 
     491    while(nb_dryrun_cycles_left > 0 && 
     492          nb_succesful_cycles < MIN_SUCCESSFUL_DRYRUN_CYCLES ) { 
     493 
     494        waitForPeriod(); 
     495 
     496        // align the received streams 
     497        int64_t sp_lag; 
     498        for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 
     499                it != m_ReceiveProcessors.end(); 
     500                ++it ) { 
     501            uint64_t ts_sp=(*it)->getTimeAtPeriod(); 
     502            uint64_t ts_sync=m_SyncSource->getTimeAtPeriod(); 
     503 
     504            sp_lag = diffTicks(ts_sp, ts_sync); 
     505            debugOutput( DEBUG_LEVEL_VERBOSE, "  SP(%p) TS=%011llu - TS=%011llu = %04lld\n",  
     506                (*it), ts_sp, ts_sync, sp_lag); 
     507            // sync the other receive SP's to the sync source 
     508//             if((*it) != m_SyncSource) { 
     509//                 if(!(*it)->m_data_buffer->syncCorrectLag(sp_lag)) { 
     510//                         debugOutput(DEBUG_LEVEL_VERBOSE,"could not syncCorrectLag(%11lld) for stream processor (%p)\n", 
     511//                                 sp_lag, *it); 
     512//                 } 
     513//             } 
     514        } 
     515 
    444516 
    445517        if (dryRun()) { 
     
    455527 
    456528    if(nb_dryrun_cycles_left == 0) { 
    457         debugOutput( DEBUG_LEVEL_VERBOSE, " max # dry-run cycles achieved without steady-state...\n" ); 
    458         return false; 
    459     } 
    460     debugOutput( DEBUG_LEVEL_VERBOSE, " dry-run resulted in steady-state...\n" ); 
    461  
     529        debugOutput( DEBUG_LEVEL_VERBOSE, " max # dry-run cycles achieved without aligned steady-state...\n" ); 
     530        return false; 
     531    } 
     532    debugOutput( DEBUG_LEVEL_VERBOSE, " dry-run resulted in aligned steady-state...\n" );*/ 
     533     
    462534    // now we should clear the xrun flags 
    463535    resetXrunCounters(); 
    464  
    465536    // and off we go 
    466537    return true; 
     
    913984    // NOTE: before waitForPeriod() is called again, both the transmit 
    914985    //       and the receive processors should have done their transfer. 
    915     m_time_of_transfer=m_SyncSource->getTimeAtPeriod(); 
     986    m_time_of_transfer = m_SyncSource->getTimeAtPeriod(); 
    916987    debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "transfer at %llu ticks...\n", 
    917988        m_time_of_transfer); 
  • branches/ppalmers-streaming/src/libstreaming/util/cycletimer.h

    r707 r712  
    156156    return x; 
    157157 
     158} 
     159 
     160/** 
     161 * @brief Computes the sum of two cycle values 
     162 * 
     163 * This function computes a sum between cycles 
     164 * such that it respects wrapping (at 8000 cycles). 
     165 * 
     166 * The passed arguments are assumed to be valid cycle numbers, 
     167 * i.e. they should be wrapped at 8000 cycles 
     168 * 
     169 * See addTicks 
     170 * 
     171 * @param x First cycle value 
     172 * @param y Second cycle value 
     173 * @return the sum x+y, wrapped 
     174 */ 
     175static inline unsigned int addCycles(unsigned int x, unsigned int y) { 
     176    unsigned int sum = x + y; 
     177#ifdef DEBUG 
     178    if (x >= CYCLES_PER_SECOND || y >= CYCLES_PER_SECOND ) { 
     179        debugWarning("At least one argument not wrapped correctly: x=%u, y=%u\n",x,y); 
     180    } 
     181#endif 
     182 
     183    // since both x and y are < CYCLES_PER_SECOND this should be enough to unwrap 
     184    if (sum > CYCLES_PER_SECOND) sum -= CYCLES_PER_SECOND; 
     185    return sum; 
    158186} 
    159187 
  • branches/ppalmers-streaming/src/libutil/TimestampedBuffer.cpp

    r707 r712  
    152152        debugWarning("(%p) rate (%10.5f) more that 10%% off nominal (rate=%10.5f, diff="TIMESTAMP_FORMAT_SPEC", update_period=%d)\n", 
    153153                     this, rate,m_nominal_rate,diff, m_update_period); 
    154         dumpInfo(); 
     154        //dumpInfo(); 
    155155        return m_nominal_rate; 
    156156    } else { 
     
    403403    } else { 
    404404        // add the data payload to the ringbuffer 
    405         if (ffado_ringbuffer_write(m_event_buffer,data,write_size) < write_size) 
     405        size_t written = ffado_ringbuffer_write(m_event_buffer, data, write_size); 
     406        if (written < write_size) 
    406407        { 
     408            debugWarning("ringbuffer full, %u, %u\n", write_size, written); 
    407409            return false; 
    408410        } 
     
    710712    EXIT_CRITICAL_SECTION; 
    711713 
    712     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "for (%p) to " 
     714    debugOutput(DEBUG_LEVEL_VERBOSE, "for (%p) to " 
    713715                                          TIMESTAMP_FORMAT_SPEC" => "TIMESTAMP_FORMAT_SPEC", NTS=" 
    714716                                          TIMESTAMP_FORMAT_SPEC", DLL2=%f, RATE=%f\n", 
     
    761763                this, new_timestamp, ts, m_buffer_next_tail_timestamp, m_dll_e2, getRate()); 
    762764 
     765} 
     766 
     767/** 
     768 * @brief Synchronize the buffer head to a specified timestamp 
     769 * 
     770 * Try to synchronize the buffer head to a specific timestamp. This 
     771 * can mean adding or removing samples to/from the buffer such that 
     772 * the buffer head aligns with the specified timestamp. The alignment 
     773 * is within ts +/- Tsample/2 
     774 * 
     775 * @param target the timestamp to align to 
     776 * @return true if alignment succeeded, false if not  
     777 */ 
     778bool 
     779TimestampedBuffer::syncBufferHeadToTimestamp(ffado_timestamp_t target) 
     780{ 
     781    uint64_t ts_head; 
     782    uint64_t ts_target=(uint64_t)target; 
     783    signed int fc; 
     784    int32_t lag_ticks; 
     785    float lag_frames; 
     786 
     787    ffado_timestamp_t ts_head_tmp; 
     788    getBufferHeadTimestamp(&ts_head_tmp, &fc); 
     789    ts_head=(uint64_t)ts_head_tmp; 
     790    // if target > ts_head then the wanted buffer head timestamp 
     791    // is later than the actual. This means that we (might) have to drop 
     792    // some frames. 
     793    lag_ticks=diffTicks(ts_target, ts_head); 
     794    float rate=getRate(); 
     795     
     796    assert(rate!=0.0); 
     797 
     798    lag_frames=(((float)lag_ticks)/rate); 
     799     
     800    debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): HEAD=%llu, TS=%llu, diff=%ld = %10.5f frames (rate=%10.5f)\n", 
     801                                      this, ts_head, ts_target, lag_ticks, lag_frames, rate); 
     802 
     803    if (lag_frames>=1.0) { 
     804        // the buffer head is too early 
     805        // ditch frames until the buffer head is on time 
     806        char dummy[getBytesPerFrame()]; // one frame of garbage 
     807        int frames_to_ditch=(int)roundf(lag_frames); 
     808        debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): ditching %d frames (@ ts=%lld)\n",this,frames_to_ditch,ts_target); 
     809         
     810        while (frames_to_ditch--) { 
     811            readFrames(1, dummy); 
     812        } 
     813         
     814    } else if (lag_frames<=-1.0) { 
     815        // the buffer head is too late 
     816        // add some padding frames 
     817        int frames_to_add=(int)roundf(lag_frames); 
     818        debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): adding %d frames (@ ts=%lld)\n",this,-frames_to_add,ts_target); 
     819         
     820        while (frames_to_add++) { 
     821             writeDummyFrame(); 
     822        } 
     823    } 
     824    getBufferHeadTimestamp(&ts_head_tmp, &fc); 
     825    ts_head=(uint64_t)ts_head_tmp; 
     826    debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): new HEAD=%llu, fc=%d, target=%llu, new diff=%lld\n", 
     827                                      this, ts_head, fc, ts_target, diffTicks(ts_target, ts_head)); 
     828    // FIXME: of course this doesn't always succeed 
     829    return true; 
     830} 
     831 
     832/** 
     833 * @brief Synchronize the buffer tail to a specified timestamp 
     834 * 
     835 * Try to synchronize the buffer tail to a specific timestamp. This 
     836 * can mean adding or removing samples to/from the buffer such that 
     837 * the buffer tail aligns with the specified timestamp. The alignment 
     838 * is within ts +/- Tsample/2 
     839 * 
     840 * @param target the timestamp to align to 
     841 * @return true if alignment succeeded, false if not  
     842 */ 
     843bool 
     844TimestampedBuffer::syncBufferTailToTimestamp(ffado_timestamp_t target) 
     845{ 
     846    uint64_t ts_tail; 
     847    uint64_t ts_target=(uint64_t)target; 
     848    signed int fc; 
     849    int32_t lag_ticks; 
     850    float lag_frames; 
     851 
     852    debugWarning("Untested\n"); 
     853     
     854    ffado_timestamp_t ts_tail_tmp; 
     855    getBufferTailTimestamp(&ts_tail_tmp, &fc); 
     856    ts_tail=(uint64_t)ts_tail_tmp; 
     857    // if target < ts_tail then the wanted buffer head timestamp 
     858    // is later than the actual. This means that we (might) have to drop 
     859    // some frames. 
     860    lag_ticks=diffTicks(ts_tail, ts_target); 
     861    float rate=getRate(); 
     862     
     863    assert(rate!=0.0); 
     864 
     865    lag_frames=(((float)lag_ticks)/rate); 
     866     
     867    debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): HEAD=%llu, TS=%llu, diff=%ld = %10.5f frames (rate=%10.5f)\n", 
     868                                      this, ts_tail, ts_target, lag_ticks, lag_frames, rate); 
     869 
     870    if (lag_frames>=1.0) { 
     871        // the buffer head is too early 
     872        // ditch frames until the buffer head is on time 
     873        char dummy[getBytesPerFrame()]; // one frame of garbage 
     874        int frames_to_ditch=(int)roundf(lag_frames); 
     875        debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): ditching %d frames (@ ts=%lld)\n",this,frames_to_ditch,ts_target); 
     876         
     877        while (frames_to_ditch--) { 
     878            readFrames(1, dummy); 
     879        } 
     880         
     881    } else if (lag_frames<=-1.0) { 
     882        // the buffer head is too late 
     883        // add some padding frames 
     884        int frames_to_add=(int)roundf(lag_frames); 
     885        debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): adding %d frames (@ ts=%lld)\n",this,-frames_to_add,ts_target); 
     886         
     887        while (frames_to_add++) { 
     888             writeDummyFrame(); 
     889        } 
     890    } 
     891    getBufferHeadTimestamp(&ts_tail_tmp, &fc); 
     892    ts_tail=(uint64_t)ts_tail_tmp; 
     893    debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): new HEAD=%llu, fc=%d, target=%llu, new diff=%lld\n", 
     894                                      this, ts_tail, fc, ts_target, diffTicks(ts_target, ts_tail)); 
     895    // FIXME: of course this doesn't always succeed 
     896    return true; 
     897} 
     898 
     899/** 
     900 * @brief correct lag 
     901 * 
     902 * Try to synchronize the buffer tail to a specific timestamp. This 
     903 * can mean adding or removing samples to/from the buffer such that 
     904 * the buffer tail aligns with the specified timestamp. The alignment 
     905 * is within ts +/- Tsample/2 
     906 * 
     907 * @param target the timestamp to align to 
     908 * @return true if alignment succeeded, false if not  
     909 */ 
     910bool 
     911TimestampedBuffer::syncCorrectLag(int64_t lag_ticks) 
     912{ 
     913    float lag_frames; 
     914    float rate=getRate(); 
     915    assert(rate!=0.0); 
     916 
     917    lag_frames=(((float)lag_ticks)/rate); 
     918    if (lag_frames >= 1.0) { 
     919        // the buffer head is too late 
     920        // add some padding frames 
     921        int frames_to_add=(int)roundf(lag_frames); 
     922        debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): adding %d frames\n",this,frames_to_add); 
     923 
     924        while (frames_to_add++) { 
     925             writeDummyFrame(); 
     926        } 
     927    } else if (lag_frames <= -1.0) { 
     928        // the buffer head is too early 
     929        // ditch frames until the buffer head is on time 
     930        char dummy[getBytesPerFrame()]; // one frame of garbage 
     931        int frames_to_ditch=(int)roundf(lag_frames); 
     932        debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): ditching %d frames\n",this,-frames_to_ditch); 
     933 
     934        while (frames_to_ditch--) { 
     935            readFrames(1, dummy); 
     936        } 
     937    } 
     938    return true; 
    763939} 
    764940 
     
    9201096//   return; 
    9211097// } 
    922      
    923     // update the DLL 
    924     ENTER_CRITICAL_SECTION; 
    925     diff = ts-m_buffer_next_tail_timestamp; 
    926     EXIT_CRITICAL_SECTION; 
     1098    ffado_timestamp_t pred_buffer_next_tail_timestamp; 
     1099    if(nbframes == m_update_period) { 
     1100        pred_buffer_next_tail_timestamp = m_buffer_next_tail_timestamp; 
     1101    } else { 
     1102        debugOutput( DEBUG_LEVEL_VERBOSE, 
     1103                     "Number of frames (%u) != update period (%u)\n", 
     1104                     nbframes, m_update_period ); 
     1105        // calculate the predicted timestamp for nframes (instead of m_update_period) 
     1106        // after the previous update. 
     1107        float rel_step = ((float)nbframes)/((float)m_update_period); 
     1108        ENTER_CRITICAL_SECTION; // FIXME: do we need these? 
     1109        ffado_timestamp_t corrected_step = (m_buffer_next_tail_timestamp - m_buffer_tail_timestamp) * rel_step; 
     1110        pred_buffer_next_tail_timestamp = m_buffer_tail_timestamp + corrected_step; 
     1111        EXIT_CRITICAL_SECTION; 
     1112         
     1113        debugOutput( DEBUG_LEVEL_VERBOSE, 
     1114                     "Updated ("TIMESTAMP_FORMAT_SPEC","TIMESTAMP_FORMAT_SPEC") to ("TIMESTAMP_FORMAT_SPEC","TIMESTAMP_FORMAT_SPEC")\n", 
     1115                     m_buffer_tail_timestamp, m_buffer_next_tail_timestamp, 
     1116                     m_buffer_tail_timestamp, pred_buffer_next_tail_timestamp); 
     1117         
     1118    } 
     1119     
     1120    // the difference between the given TS and the one predicted for this time instant 
     1121    // this is the error for the DLL 
     1122    diff = ts - pred_buffer_next_tail_timestamp; 
    9271123 
    9281124    // check whether the update is within the allowed bounds 
    929     const float max_deviation = (100.0/100.0); // maximal relative difference considered normal 
    930     ffado_timestamp_t expected_difference=m_update_period * getRate(); 
    931     ffado_timestamp_t max_abs_diff = expected_difference * max_deviation
     1125    const float max_deviation = (50.0/100.0); // maximal relative difference considered normal 
     1126    ffado_timestamp_t one_update_step = nbframes * getRate(); 
     1127    ffado_timestamp_t max_abs_diff = one_update_step * (1.0 + max_deviation)
    9321128     
    9331129    if (diff > max_abs_diff) { 
    934         debugWarning("(%p) difference rather large (+): diff="TIMESTAMP_FORMAT_SPEC", expected="TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC"\n", 
    935             this, diff, expected_difference, ts, m_buffer_next_tail_timestamp); 
     1130        debugWarning("(%p) difference rather large (+): diff="TIMESTAMP_FORMAT_SPEC", max="TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC"\n", 
     1131            this, diff, max_abs_diff, ts, pred_buffer_next_tail_timestamp); 
    9361132//         debugShowBackLogLines(40); 
    937      
    938         // we can limit the difference 
    939         // we can't discard it because that would prevent us from tracking the samplerate 
    940         diff = max_abs_diff; 
    941   
    9421133    } else if (diff < -max_abs_diff) { 
    943         debugWarning("(%p) difference rather large (-): diff="TIMESTAMP_FORMAT_SPEC", expected="TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC"\n", 
    944             this, diff, expected_difference, ts, m_buffer_next_tail_timestamp); 
     1134        debugWarning("(%p) difference rather large (-): diff="TIMESTAMP_FORMAT_SPEC", max="TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC"\n", 
     1135            this, diff, -max_abs_diff, ts, pred_buffer_next_tail_timestamp); 
    9451136//         debugShowBackLogLines(40); 
    946          
    947         // we can limit the difference 
    948         // we can't discard it because that would prevent us from tracking the samplerate 
    949         diff = -max_abs_diff; 
    950     } 
    951  
    952     // idea to implement it for nbframes values that differ from m_update_period: 
    953     // diff = diff * nbframes/m_update_period 
    954     // m_buffer_next_tail_timestamp = m_buffer_tail_timestamp + diff 
     1137    } 
    9551138 
    9561139    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%p): diff="TIMESTAMP_FORMAT_SPEC" ", 
    9571140                this, diff); 
    958  
    959     // the maximal difference we can allow (64secs) 
    960 //     const ffado_timestamp_t max=m_wrap_at/2; 
    961 //  
    962 //     if(diff > max) { 
    963 //         diff -= m_wrap_at; 
    964 //     } else if (diff < -max) { 
    965 //         diff += m_wrap_at; 
    966 //     } 
    9671141 
    9681142    double err=diff; 
     
    9711145                    diff, err); 
    9721146    debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "B: FC=%10u, TS="TIMESTAMP_FORMAT_SPEC", NTS="TIMESTAMP_FORMAT_SPEC"\n", 
    973                     m_framecounter, m_buffer_tail_timestamp, m_buffer_next_tail_timestamp); 
     1147                    m_framecounter, m_buffer_tail_timestamp, pred_buffer_next_tail_timestamp); 
    9741148 
    9751149    ENTER_CRITICAL_SECTION; 
    9761150    m_framecounter += nbframes; 
    9771151 
    978     m_buffer_tail_timestamp=m_buffer_next_tail_timestamp; 
    979     m_buffer_next_tail_timestamp += (ffado_timestamp_t)(m_dll_b * err + m_dll_e2); 
     1152    m_buffer_tail_timestamp = pred_buffer_next_tail_timestamp; 
     1153    m_buffer_next_tail_timestamp = pred_buffer_next_tail_timestamp + (ffado_timestamp_t)(m_dll_b * err + m_dll_e2); 
    9801154//    m_buffer_tail_timestamp=ts; 
    9811155//    m_buffer_next_tail_timestamp += (ffado_timestamp_t)(m_dll_b * err + m_dll_e2); 
  • branches/ppalmers-streaming/src/libutil/TimestampedBuffer.h

    r705 r712  
    133133    void setBufferHeadTimestamp(ffado_timestamp_t new_timestamp); 
    134134 
     135    // sync related, also drops or add frames when necessary 
     136    bool syncBufferHeadToTimestamp(ffado_timestamp_t ts); 
     137    bool syncBufferTailToTimestamp(ffado_timestamp_t ts); 
     138    bool syncCorrectLag(int64_t ts); 
     139     
    135140    ffado_timestamp_t getTimestampFromTail(int nframes); 
    136141    ffado_timestamp_t getTimestampFromHead(int nframes); 
  • branches/ppalmers-streaming/src/maudio/maudio_avdevice.h

    r705 r712  
    3232#include "bebob/bebob_avdevice.h" 
    3333 
    34 #include "libstreaming/amdtp/AmdtpStreamProcessor.h" 
     34#include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 
     35#include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 
    3536#include "libstreaming/amdtp/AmdtpPort.h" 
    3637#include "libstreaming/amdtp/AmdtpPortInfo.h" 
  • branches/ppalmers-streaming/src/SConscript

    r705 r712  
    153153        libstreaming/amdtp/AmdtpPort.cpp \ 
    154154        libstreaming/amdtp/AmdtpPortInfo.cpp \ 
    155         libstreaming/amdtp/AmdtpStreamProcessor.cpp \ 
     155        libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp \ 
     156        libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp \ 
    156157' ) 
    157158