- Timestamp:
- 11/04/07 03:33:35 (15 years ago)
- Files:
-
- branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpPort.cpp (moved) (moved from branches/ppalmers-streaming/src/libstreaming/AmdtpPort.cpp)
- branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpPort.h (moved) (moved from branches/ppalmers-streaming/src/libstreaming/AmdtpPort.h)
- branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpPortInfo.cpp (moved) (moved from branches/ppalmers-streaming/src/libstreaming/AmdtpPortInfo.cpp)
- branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpPortInfo.h (moved) (moved from branches/ppalmers-streaming/src/libstreaming/AmdtpPortInfo.h)
- branches/ppalmers-streaming/src/libstreaming/AmdtpStreamProcessor.cpp (modified) (15 diffs)
- branches/ppalmers-streaming/src/libstreaming/AmdtpStreamProcessor.h (modified) (2 diffs)
- branches/ppalmers-streaming/src/libstreaming/cycletimer.h (modified) (5 diffs)
- branches/ppalmers-streaming/src/libstreaming/IsoHandlerManager.cpp (modified) (2 diffs)
- branches/ppalmers-streaming/src/libstreaming/IsoHandlerManager.h (modified) (2 diffs)
- branches/ppalmers-streaming/src/libstreaming/motu/MotuPort.cpp (moved) (moved from branches/ppalmers-streaming/src/libstreaming/MotuPort.cpp)
- branches/ppalmers-streaming/src/libstreaming/motu/MotuPort.h (moved) (moved from branches/ppalmers-streaming/src/libstreaming/MotuPort.h)
- branches/ppalmers-streaming/src/libstreaming/motu/MotuPortInfo.cpp (moved) (moved from branches/ppalmers-streaming/src/libstreaming/MotuPortInfo.cpp)
- branches/ppalmers-streaming/src/libstreaming/motu/MotuPortInfo.h (moved) (moved from branches/ppalmers-streaming/src/libstreaming/MotuPortInfo.h)
- branches/ppalmers-streaming/src/libstreaming/motu/MotuStreamProcessor.cpp (moved) (moved from branches/ppalmers-streaming/src/libstreaming/MotuStreamProcessor.cpp)
- branches/ppalmers-streaming/src/libstreaming/motu/MotuStreamProcessor.h (moved) (moved from branches/ppalmers-streaming/src/libstreaming/MotuStreamProcessor.h)
- branches/ppalmers-streaming/src/libstreaming/StreamProcessor.cpp (modified) (4 diffs)
- branches/ppalmers-streaming/src/libstreaming/StreamProcessor.h (modified) (4 diffs)
- branches/ppalmers-streaming/src/libstreaming/StreamProcessorManager.cpp (modified) (14 diffs)
- branches/ppalmers-streaming/src/libstreaming/StreamProcessorManager.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/ppalmers-streaming/src/libstreaming/AmdtpStreamProcessor.cpp
r554 r703 38 38 namespace Streaming { 39 39 40 IMPL_DEBUG_MODULE( AmdtpTransmitStreamProcessor, AmdtpTransmitStreamProcessor, DEBUG_LEVEL_ NORMAL);41 IMPL_DEBUG_MODULE( AmdtpReceiveStreamProcessor, AmdtpReceiveStreamProcessor, DEBUG_LEVEL_ NORMAL);40 IMPL_DEBUG_MODULE( AmdtpTransmitStreamProcessor, AmdtpTransmitStreamProcessor, DEBUG_LEVEL_VERBOSE ); 41 IMPL_DEBUG_MODULE( AmdtpReceiveStreamProcessor, AmdtpReceiveStreamProcessor, DEBUG_LEVEL_VERBOSE ); 42 42 43 43 … … 84 84 85 85 if (cycle<0) { 86 debugOutput(DEBUG_LEVEL_ VERY_VERBOSE,"Xmit handler for cycle %d, (running=%d, enabled=%d,%d)\n",87 cycle, m_running , m_disabled, m_is_disabled);86 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,"Xmit handler for cycle %d, (running=%d)\n", 87 cycle, m_running); 88 88 89 89 *tag = 0; … … 94 94 } 95 95 96 debugOutput(DEBUG_LEVEL_ VERY_VERBOSE,"Xmit handler for cycle %d, (running=%d, enabled=%d,%d)\n",97 cycle, m_running , m_disabled, m_is_disabled);96 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,"Xmit handler for cycle %d, (running=%d)\n", 97 cycle, m_running); 98 98 99 99 m_last_cycle=cycle; … … 153 153 uint64_t ts_head; 154 154 signed int fc; 155 if (!m_disabled && m_is_disabled) { // this means that we are trying to enable 156 // check if we are on or past the enable point 157 int cycles_past_enable=diffCycles(cycle, m_cycle_to_enable_at); 158 159 if (cycles_past_enable >= 0) { 160 m_is_disabled=false; 161 162 debugOutput(DEBUG_LEVEL_VERBOSE,"Enabling StreamProcessor %p at %u\n", this, cycle); 163 164 // initialize the buffer head & tail 165 ffado_timestamp_t ts_head_tmp; 166 m_SyncSource->m_data_buffer->getBufferHeadTimestamp(&ts_head_tmp, &fc); // thread safe 167 ts_head=(uint64_t)ts_head_tmp; 168 169 // the number of cycles the sync source lags (> 0) 170 // or leads (< 0) 171 int sync_lag_cycles=diffCycles(cycle, m_SyncSource->getLastCycle()); 172 173 // account for the cycle lag between sync SP and this SP 174 // the last update of the sync source's timestamps was sync_lag_cycles 175 // cycles before the cycle we are calculating the timestamp for. 176 // if we were to use one-frame buffers, you would expect the 177 // frame that is sent on cycle CT to have a timestamp T1. 178 // ts_head however is for cycle CT-sync_lag_cycles, and lies 179 // therefore sync_lag_cycles * TICKS_PER_CYCLE earlier than 180 // T1. 181 ts_head = addTicks(ts_head, (sync_lag_cycles) * TICKS_PER_CYCLE); 182 183 ts_head = substractTicks(ts_head, TICKS_PER_CYCLE); 184 185 // account for the number of cycles we are too late to enable 186 ts_head = addTicks(ts_head, cycles_past_enable * TICKS_PER_CYCLE); 187 188 // account for one extra packet of frames 189 ts_head = substractTicks(ts_head, 190 (uint32_t)((float)m_syt_interval * m_SyncSource->m_data_buffer->getRate())); 191 192 m_data_buffer->setBufferHeadTimestamp(ts_head); 193 194 #ifdef DEBUG 195 if ((unsigned int)m_data_buffer->getFrameCounter() != m_data_buffer->getBufferSize()) { 196 debugWarning("m_data_buffer->getFrameCounter() != m_data_buffer->getBufferSize()\n"); 197 } 198 #endif 199 debugOutput(DEBUG_LEVEL_VERBOSE,"XMIT TS SET: TS=%10llu, LAG=%03d, FC=%4d\n", 200 ts_head, sync_lag_cycles, m_data_buffer->getFrameCounter()); 201 } else { 202 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, 203 "will enable StreamProcessor %p at %u, now is %d\n", 204 this, m_cycle_to_enable_at, cycle); 205 } 206 } else if (m_disabled && !m_is_disabled) { 207 // trying to disable 208 debugOutput(DEBUG_LEVEL_VERBOSE,"disabling StreamProcessor %p at %u\n", 209 this, cycle); 210 m_is_disabled=true; 211 } 212 155 uint64_t presentation_time; 156 unsigned int presentation_cycle; 157 int cycles_until_presentation; 158 159 const int min_cycles_beforehand = 2; // FIXME: should become a define 160 const int max_cycles_beforehand = 15; // FIXME: should become a define 161 162 if( !m_running || !m_data_buffer->isEnabled() ) { 163 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, 164 "Not running (%d) or buffer not enabled (enabled=%d)\n", 165 m_running, m_data_buffer->isEnabled()); 166 167 // not running or not enabled 168 goto send_empty_packet; 169 } 170 171 try_block_of_frames: 172 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "Try for cycle %d\n", cycle); 173 // check whether the packet buffer has packets for us to send. 213 174 // the base timestamp is the one of the next sample in the buffer 214 175 ffado_timestamp_t ts_head_tmp; … … 216 177 ts_head=(uint64_t)ts_head_tmp; 217 178 218 // we send a packet some cycles in advance, to avoid the 219 // following situation: 220 // suppose we are only a few ticks away from 221 // the moment to send this packet. therefore we decide 222 // not to send the packet, but send it in the next cycle. 223 // This means that the next time point will be 3072 ticks 224 // later, making that the timestamp will be expired when the 225 // packet is sent, unless TRANSFER_DELAY > 3072. 226 // this means that we need at least one cycle of extra buffering. 227 uint32_t ticks_to_advance = TICKS_PER_CYCLE * TRANSMIT_ADVANCE_CYCLES; 228 229 // if cycle lies cycle_diff cycles in the future, we should 230 // queue this packet cycle_diff * TICKS_PER_CYCLE earlier than 231 // we would if it were to be sent immediately. 232 ticks_to_advance += cycle_diff * TICKS_PER_CYCLE; 233 234 // determine the 'now' time in ticks 235 uint32_t cycle_timer=CYCLE_TIMER_TO_TICKS(ctr); 236 237 cycle_timer = addTicks(cycle_timer, ticks_to_advance); 238 239 // time until the packet is to be sent (if > 0: send packet) 240 int32_t until_next=diffTicks(ts_head, cycle_timer); 241 242 // if until_next < 0 we should send a filled packet 243 // otherwise we should send a NO-DATA packet 244 if((until_next<0) && (m_running)) { 245 // add the transmit transfer delay to construct the playout time (=SYT timestamp) 246 uint32_t ts_packet=addTicks(ts_head, TRANSMIT_TRANSFER_DELAY); 247 248 // if we are disabled, send a silent packet 249 // and advance the buffer head timestamp 250 if(m_is_disabled) { 251 252 // transmitSilenceBlock((char *)(data+8), m_syt_interval, 0); 253 // m_dbc += fillDataPacketHeader(packet, length, ts_packet); 254 // 255 // debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT SYNC: CY=%04u TSH=%011llu TSP=%011lu\n", 256 // cycle, ts_head, ts_packet); 257 // 258 // // update the base timestamp 259 // uint32_t ts_step=(uint32_t)((float)(m_syt_interval) 260 // *m_SyncSource->m_data_buffer->getRate()); 261 // 262 // // the next buffer head timestamp 263 // ts_head=addTicks(ts_head,ts_step); 264 // m_data_buffer->setBufferHeadTimestamp(ts_head); 265 // 266 // no-data 267 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT SYNC: CY=%04u NONE\n", cycle); 268 m_dbc += fillNoDataPacketHeader(packet, length); 269 // defer to make sure we get to be enabled asap 270 return RAW1394_ISO_DEFER; 271 272 } else { // enabled & packet due, read from the buffer 273 if (m_data_buffer->readFrames(m_syt_interval, (char *)(data + 8))) { 274 m_dbc += fillDataPacketHeader(packet, length, ts_packet); 275 276 // process all ports that should be handled on a per-packet base 277 // this is MIDI for AMDTP (due to the need of DBC) 278 if (!encodePacketPorts((quadlet_t *)(data+8), m_syt_interval, packet->dbc)) { 279 debugWarning("Problem encoding Packet Ports\n"); 280 } 281 282 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT DATA: CY=%04u TSH=%011llu TSP=%011lu\n", 283 cycle, ts_head, ts_packet); 284 285 return RAW1394_ISO_OK; 286 287 } else if (now_cycles<cycle) { 288 // we can still postpone the queueing of the packets 289 // because the ISO transmit packet buffer is not empty yet 290 return RAW1394_ISO_AGAIN; 291 292 } else { // there is no more data in the ringbuffer 293 // compose a silent packet, we should always 294 // send a valid packet 295 transmitSilenceBlock((char *)(data+8), m_syt_interval, 0); 296 m_dbc += fillDataPacketHeader(packet, length, ts_packet); 297 298 debugWarning("Transmit buffer underrun (now %d, queue %d, target %d)\n", 299 now_cycles, cycle, TICKS_TO_CYCLES(ts_packet)); 300 // signal underrun 301 m_xruns++; 302 // disable the processing, will be re-enabled when 303 // the xrun is handled 304 m_disabled=true; 305 m_is_disabled=true; 306 307 return RAW1394_ISO_DEFER; 308 } 309 } 310 311 } else { // no packet due, send no-data packet 312 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT NONE: CY=%04u TSH=%011llu\n", 313 cycle, ts_head); 314 315 m_dbc += fillNoDataPacketHeader(packet, length); 316 return RAW1394_ISO_DEFER; 317 } 318 319 // we shouldn't get here 179 // first calculate the presentation time of the samples 180 presentation_time = addTicks(ts_head, TRANSMIT_TRANSFER_DELAY); 181 182 // calculate the cycle this block should be presented in 183 // (this is just a virtual calculation since at that time it should 184 // already be in the device's buffer) 185 presentation_cycle = (unsigned int)(TICKS_TO_CYCLES( presentation_time )); 186 187 // we can check whether this cycle is within the 'window' we have 188 // to send this packet. 189 // first calculate the number of cycles left before presentation time 190 cycles_until_presentation = diffCycles( presentation_cycle, cycle ); 191 192 // two different options: 193 // 1) there are not enough frames for one packet 194 // => determine wether this is a problem, since we might still 195 // have some time to send it 196 // 2) there are enough packets 197 // => determine whether we have to send them in this packet 198 if (fc < (signed int)m_syt_interval) { 199 // not enough frames in the buffer, 200 debugOutput(DEBUG_LEVEL_VERBOSE, 201 "Insufficient frames: CY=%04u, PTC=%04u, CUP=%04d\n", 202 cycle, presentation_cycle, cycles_until_presentation); 203 // we can still postpone the queueing of the packets 204 // if we are far enough ahead of the presentation time 205 if( cycles_until_presentation <= min_cycles_beforehand ) { 206 // we have an invalid timestamp or we are too late 207 // meaning that we in some sort of xrun state 208 // signal xrun situation ??HERE?? 209 m_xruns++; 210 } else { 211 // there is still time left to send the packet 212 } 213 // in any case we send an empty packet on this cycle 214 goto send_empty_packet; // UGLY but effective 215 } else { 216 // there are enough frames, so check the time they are intended for 217 // all frames have a certain 'time window' in which they can be sent 218 // this corresponds to the range of the timestamp mechanism: 219 // we can send a packet 15 cycles in advance of the 'presentation time' 220 // in theory we can send the packet up till one cycle before the presentation time, 221 // however this is not very smart. 222 223 // There are 3 options: 224 // 1) the frame block is too early 225 // => send an empty packet 226 // 2) the frame block is within the window 227 // => send it 228 // 3) the frame block is too late 229 // => discard (and raise xrun?) 230 // get next block of frames and repeat 231 232 if (cycles_until_presentation <= min_cycles_beforehand) { 233 // we are too late 234 debugOutput(DEBUG_LEVEL_VERBOSE, 235 "Too late: CY=%04u, PTC=%04u, CUP=%04d, TSP=%011llu (%04u)\n", 236 cycle, 237 presentation_cycle, cycles_until_presentation, 238 presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 239 // remove the samples 240 m_data_buffer->dropFrames(m_syt_interval); 241 242 // signal some xrun situation ??HERE?? 243 m_xruns++; 244 245 // try a new block of frames 246 goto try_block_of_frames; // UGLY but effective 247 } else if (cycles_until_presentation >= max_cycles_beforehand) { 248 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, 249 "Too early: CY=%04u, PTC=%04u, CUP=%04d, TSP=%011llu (%04u)\n", 250 cycle, 251 presentation_cycle, cycles_until_presentation, 252 presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 253 // we are too early, send only an empty packet 254 goto send_empty_packet; // UGLY but effective 255 } else { 256 // send the packet 257 goto send_packet; // UGLY but effective 258 } 259 } 260 261 debugError("Should never reach this code!\n"); 320 262 return RAW1394_ISO_ERROR; 321 263 264 send_empty_packet: 265 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT NONE: CY=%04u, TSP=%011llu (%04u)\n", 266 cycle, 267 presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 268 269 m_dbc += fillNoDataPacketHeader(packet, length); 270 return RAW1394_ISO_DEFER; 271 272 send_packet: 273 if (m_data_buffer->readFrames(m_syt_interval, (char *)(data + 8))) { 274 m_dbc += fillDataPacketHeader(packet, length, presentation_time); 275 276 // process all ports that should be handled on a per-packet base 277 // this is MIDI for AMDTP (due to the need of DBC) 278 if (!encodePacketPorts((quadlet_t *)(data+8), m_syt_interval, packet->dbc)) { 279 debugWarning("Problem encoding Packet Ports\n"); 280 } 281 282 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT DATA: CY=%04u, TSH=%011llu (%04u), TSP=%011llu (%04u)\n", 283 cycle, 284 ts_head, (unsigned int)TICKS_TO_CYCLES(ts_head), 285 presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time)); 286 287 return RAW1394_ISO_OK; 288 } 289 // else: 290 debugError("This is impossible, since we checked the buffer size before!\n"); 291 return RAW1394_ISO_ERROR; 322 292 } 323 293 … … 384 354 m_WakeupStat.reset(); 385 355 386 // we have to make sure that the buffer HEAD timestamp 387 // lies in the future for every possible buffer fill case. 388 int offset=(int)(m_ringbuffer_size_frames*getTicksPerFrame()); 389 390 m_data_buffer->setTickOffset(offset); 356 m_data_buffer->setTickOffset(0); 391 357 392 358 // reset all non-device specific stuff … … 589 555 590 556 bool AmdtpTransmitStreamProcessor::prepareForStop() { 591 disable();592 557 return true; 593 558 } 594 559 595 560 bool AmdtpTransmitStreamProcessor::prepareForEnable(uint64_t time_to_enable_at) { 596 597 debugOutput(DEBUG_LEVEL_VERBOSE,"Preparing to enable...\n");598 599 // for the transmit SP, we have to initialize the600 // buffer timestamp to something sane, because this timestamp601 // is used when it is SyncSource602 603 // the time we initialize to will determine the time at which604 // the first sample in the buffer will be sent, so we should605 // make it at least 'time_to_enable_at'606 607 uint64_t now=m_handler->getCycleTimer();608 unsigned int now_secs=CYCLE_TIMER_GET_SECS(now);609 610 // check if a wraparound on the secs will happen between611 // now and the time we start612 int until_enable=(int)time_to_enable_at - (int)CYCLE_TIMER_GET_CYCLES(now);613 614 if(until_enable>4000) {615 // wraparound on CYCLE_TIMER_GET_CYCLES(now)616 // this means that we are late starting up,617 // and that the start lies in the previous second618 if (now_secs==0) now_secs=127;619 else now_secs--;620 } else if (until_enable<-4000) {621 // wraparound on time_to_enable_at622 // this means that we are early and that the start623 // point lies in the next second624 now_secs++;625 if (now_secs>=128) now_secs=0;626 }627 628 uint64_t ts_head= now_secs*TICKS_PER_SECOND;629 ts_head+=time_to_enable_at*TICKS_PER_CYCLE;630 631 // we also add the nb of cycles we transmit in advance632 ts_head=addTicks(ts_head, TRANSMIT_ADVANCE_CYCLES*TICKS_PER_CYCLE);633 634 m_data_buffer->setBufferTailTimestamp(ts_head);635 636 561 637 562 if (!StreamProcessor::prepareForEnable(time_to_enable_at)) { … … 666 591 m_PeriodStat.mark(m_data_buffer->getBufferFill()); 667 592 668 debugOutput(DEBUG_LEVEL_ VERY_VERBOSE, "AmdtpTransmitStreamProcessor::putFrames(%d, %llu)\n", nbframes, ts);593 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "AmdtpTransmitStreamProcessor::putFrames(%d, %llu)\n", nbframes, ts); 669 594 670 595 // transfer the data 671 596 m_data_buffer->blockProcessWriteFrames(nbframes, ts); 672 597 673 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " New timestamp: %llu\n", ts); 674 675 return true; 676 } 598 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, " New timestamp: %llu\n", ts); 599 600 return true; // FIXME: what about failure? 601 } 602 603 bool AmdtpTransmitStreamProcessor::putFramesDry(unsigned int nbframes, int64_t ts) { 604 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "AmdtpTransmitStreamProcessor::putFramesDry(%d, %llu)\n", nbframes, ts); 605 606 bool retval; 607 char dummybuffer[sizeof(quadlet_t)*nbframes*m_dimension]; 608 609 transmitSilenceBlock(dummybuffer, nbframes, 0); 610 // add the silence data to the ringbuffer 611 if(m_data_buffer->writeFrames(nbframes, dummybuffer, ts)) { 612 retval=true; 613 } else { 614 debugWarning("Could not write to event buffer\n"); 615 retval=false; 616 } 617 618 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, " New timestamp: %llu\n", ts); 619 return retval; 620 } 621 677 622 /* 678 623 * write received events to the stream ringbuffers. … … 800 745 IEC61883_AM824_LABEL_MIDI_1X)); 801 746 802 debugOutput(DEBUG_LEVEL_ VERY_VERBOSE, "MIDI port %s, pos=%d, loc=%d, dbc=%d, nevents=%d, dim=%d\n",747 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "MIDI port %s, pos=%d, loc=%d, dbc=%d, nevents=%d, dim=%d\n", 803 748 mp->getName().c_str(), mp->getPosition(), mp->getLocation(), dbc, nevents, m_dimension); 804 debugOutput(DEBUG_LEVEL_ VERY_VERBOSE, "base=%p, target=%p, value=%08X\n",749 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "base=%p, target=%p, value=%08X\n", 805 750 data, target_event, tmpval); 806 751 … … 937 882 } 938 883 939 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"ch%2u: CY=%4u, SYT=%08X (%4ucy + %04uticks) (running=%d , disabled=%d,%d)\n",884 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"ch%2u: CY=%4u, SYT=%08X (%4ucy + %04uticks) (running=%d)\n", 940 885 channel, cycle,ntohs(packet->syt), 941 886 CYCLE_TIMER_GET_CYCLES(ntohs(packet->syt)), CYCLE_TIMER_GET_OFFSET(ntohs(packet->syt)), 942 m_running ,m_disabled,m_is_disabled);887 m_running); 943 888 944 889 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, … … 952 897 953 898 #endif 954 if (!m_disabled && m_is_disabled) { // this means that we are trying to enable955 // check if we are on or past the enable point956 int cycles_past_enable=diffCycles(cycle, m_cycle_to_enable_at);957 958 if (cycles_past_enable >= 0) {959 m_is_disabled=false;960 debugOutput(DEBUG_LEVEL_VERBOSE,"Enabling StreamProcessor %p at %d (SYT=%04X)\n",961 this, cycle, ntohs(packet->syt));962 // the previous timestamp is the one we need to start with963 // because we're going to update the buffer again this loop964 // using writeframes965 m_data_buffer->setBufferTailTimestamp(m_last_timestamp);966 967 } else {968 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,969 "will enable StreamProcessor %p at %u, now is %d\n",970 this, m_cycle_to_enable_at, cycle);971 }972 } else if (m_disabled && !m_is_disabled) {973 // trying to disable974 debugOutput(DEBUG_LEVEL_VERBOSE,"disabling StreamProcessor %p at %u\n", this, cycle);975 m_is_disabled=true;976 }977 899 978 900 // check if this is a valid packet … … 1011 933 } 1012 934 1013 //=> don't process the stream samples when it is not enabled.1014 if(m_is_disabled) {1015 1016 // we keep track of the timestamp here1017 // this makes sure that we will have a somewhat accurate1018 // estimate as to when a period might be ready. i.e. it will not1019 // be ready earlier than this timestamp + period time1020 1021 // the next (possible) sample is not this one, but lies1022 // SYT_INTERVAL * rate later1023 uint64_t ts=addTicks(m_last_timestamp,1024 (uint64_t)((float)m_syt_interval * getTicksPerFrame()));1025 1026 // set the timestamp as if there will be a sample put into1027 // the buffer by the next packet.1028 m_data_buffer->setBufferTailTimestamp(ts);1029 1030 return RAW1394_ISO_DEFER;1031 }1032 1033 935 #ifdef DEBUG_OFF 1034 936 if((cycle % 1000) == 0) { … … 1065 967 } else { 1066 968 1067 debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",1068 cycle, m_data_buffer->getFrameCounter(), m_handler->getPacketCount());969 // debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n", 970 // cycle, m_data_buffer->getFrameCounter(), m_handler->getPacketCount()); 1069 971 1070 972 m_xruns++; 1071 1072 // disable the processing, will be re-enabled when1073 // the xrun is handled1074 m_disabled=true;1075 m_is_disabled=true;1076 973 1077 974 retval=RAW1394_ISO_DEFER; … … 1275 1172 bool AmdtpReceiveStreamProcessor::getFrames(unsigned int nbframes, int64_t ts) { 1276 1173 1277 m_PeriodStat.mark(m_data_buffer->getBufferFill());1278 uint64_t ts_head;1279 signed int fc;1280 int32_t lag_ticks;1281 float lag_frames;1282 1283 // in order to sync up multiple received streams, we should1284 // use the ts parameter. It specifies the time of the block's1285 // first sample.1286 1287 ffado_timestamp_t ts_head_tmp;1288 m_data_buffer->getBufferHeadTimestamp(&ts_head_tmp, &fc);1289 ts_head=(uint64_t)ts_head_tmp;1290 lag_ticks=diffTicks(ts, ts_head);1291 float rate=m_data_buffer->getRate();1292 1293 assert(rate!=0.0);1294 1295 lag_frames=(((float)lag_ticks)/rate);1296 1297 if (lag_frames>=1.0) {1298 // the stream leads1299 debugOutput( DEBUG_LEVEL_VERBOSE, "stream (%p): lags with %6d ticks = %10.5f frames (rate=%10.5f)\n",this,lag_ticks,lag_frames,rate);1300 1301 if (lag_frames>=10.0) {1302 debugOutput( DEBUG_LEVEL_VERBOSE, " %lld, %llu, %d\n", ts, ts_head, fc);1303 }1304 1305 // ditch the excess frames1306 char dummy[m_data_buffer->getBytesPerFrame()]; // one frame of garbage1307 int frames_to_ditch=(int)(lag_frames);1308 debugOutput( DEBUG_LEVEL_VERBOSE, "stream (%p): ditching %d frames (@ ts=%lld)\n",this,frames_to_ditch,ts);1309 1310 while (frames_to_ditch--) {1311 // m_data_buffer->readFrames(1, dummy);1312 }1313 1314 } else if (lag_frames<=-1.0) {1315 // the stream leads1316 debugOutput( DEBUG_LEVEL_VERBOSE, "stream (%p): leads with %6d ticks = %10.5f frames (rate=%10.5f)\n",this,lag_ticks,lag_frames,rate);1317 1318 if (lag_frames<=-10.0) {1319 debugOutput( DEBUG_LEVEL_VERBOSE, " %lld, %llu, %d\n", ts, ts_head, fc);1320 }1321 1322 // add some padding frames1323 int frames_to_add=(int)lag_frames;1324 debugOutput( DEBUG_LEVEL_VERBOSE, "stream (%p): adding %d frames (@ ts=%lld)\n",this,-frames_to_add,ts);1325 1326 while (frames_to_add++) {1327 // m_data_buffer->writeDummyFrame();1328 }1329 }1330 1331 1174 // ask the buffer to process nbframes of frames 1332 1175 // using it's registered client's processReadBlock(), … … 1334 1177 m_data_buffer->blockProcessReadFrames(nbframes); 1335 1178 1179 return true; 1180 } 1181 1182 bool AmdtpReceiveStreamProcessor::getFramesDry(unsigned int nbframes, int64_t ts) { 1183 int frames_to_ditch=(int)(nbframes); 1184 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): dry run %d frames (@ ts=%lld)\n", 1185 this, frames_to_ditch, ts); 1186 char dummy[m_data_buffer->getBytesPerFrame()]; // one frame of garbage 1187 1188 while (frames_to_ditch--) { 1189 m_data_buffer->readFrames(1, dummy); 1190 } 1336 1191 return true; 1337 1192 } branches/ppalmers-streaming/src/libstreaming/AmdtpStreamProcessor.h
r494 r703 96 96 97 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); 98 99 99 100 // We have 1 period of samples = m_period … … 188 189 189 190 bool getFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents to the client 191 bool getFramesDry(unsigned int nbframes, int64_t ts); 190 192 191 193 // We have 1 period of samples = m_period branches/ppalmers-streaming/src/libstreaming/cycletimer.h
r498 r703 66 66 ) 67 67 #define CYCLE_TIMER_WRAP_TICKS(x) ((x % TICKS_PER_SECOND)) 68 69 #define INVALID_TIMESTAMP_TICKS 0xFFFFFFFFFFFFFFFFULL 68 70 69 71 DECLARE_GLOBAL_DEBUG_MODULE; … … 247 249 uint64_t timestamp; 248 250 249 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT=%0 8X CY=%04X CTR=%08X\n",250 syt_timestamp, rcv_cycle,ctr_now);251 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT=%04llX CY=%u CTR=%08llX\n", 252 syt_timestamp, rcv_cycle, ctr_now); 251 253 252 254 // reconstruct the full cycle … … 309 311 if(( TICKS_TO_CYCLE_TIMER(timestamp) & 0xFFFF) != syt_timestamp) { 310 312 debugWarning("back-converted timestamp not equal to SYT\n"); 311 debugWarning("TS=%011llu TSC=%08 X SYT=%04X\n",313 debugWarning("TS=%011llu TSC=%08lX SYT=%04X\n", 312 314 timestamp, TICKS_TO_CYCLE_TIMER(timestamp), syt_timestamp); 313 315 } … … 333 335 uint64_t timestamp; 334 336 335 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT=%08 X CY=%04X CTR=%08X\n",337 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT=%08llX CY=%04X CTR=%08llX\n", 336 338 syt_timestamp,xmt_cycle,ctr_now); 337 339 … … 395 397 if(( TICKS_TO_CYCLE_TIMER(timestamp) & 0xFFFF) != syt_timestamp) { 396 398 debugWarning("back-converted timestamp not equal to SYT\n"); 397 debugWarning("TS=%011llu TSC=%08 X SYT=%04X\n",399 debugWarning("TS=%011llu TSC=%08lX SYT=%04X\n", 398 400 timestamp, TICKS_TO_CYCLE_TIMER(timestamp), syt_timestamp); 399 401 } branches/ppalmers-streaming/src/libstreaming/IsoHandlerManager.cpp
r494 r703 86 86 { 87 87 debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 88 pthread_mutex_init(&m_debug_lock, NULL); 88 89 89 90 return true; … … 107 108 // updateCycleTimers(); 108 109 110 pthread_mutex_lock(&m_debug_lock); 111 109 112 if(!iterate()) { 110 113 debugFatal("Could not iterate the isoManager\n"); 114 pthread_mutex_unlock(&m_debug_lock); 111 115 return false; 112 116 } 117 118 pthread_mutex_unlock(&m_debug_lock); 113 119 114 120 return true; branches/ppalmers-streaming/src/libstreaming/IsoHandlerManager.h
r445 r703 102 102 bool Execute(); // note that this is called in we while(running) loop 103 103 bool Init(); 104 pthread_mutex_t m_debug_lock; 104 105 105 106 // the state machine … … 149 150 Util::PosixThread *m_isoManagerThread; 150 151 151 152 152 // debug stuff 153 153 DECLARE_DEBUG_MODULE; branches/ppalmers-streaming/src/libstreaming/StreamProcessor.cpp
r494 r703 211 211 } 212 212 #endif 213 m_data_buffer->enable(); 213 214 214 215 m_disabled=false; … … 217 218 218 219 bool StreamProcessor::disable() { 220 m_data_buffer->disable(); 219 221 m_disabled=true; 220 222 return true; … … 261 263 int32_t until_next=diffTicks(time_at_period,cycle_timer); 262 264 263 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TAP=%11llu, CTR=%11llu, UTN=%11l ld\n",265 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TAP=%11llu, CTR=%11llu, UTN=%11ld\n", 264 266 time_at_period, cycle_timer, until_next 265 267 ); … … 274 276 uint64_t StreamProcessor::getTimeAtPeriodUsecs() { 275 277 return (uint64_t)((float)getTimeAtPeriod() * TICKS_PER_USEC); 278 } 279 280 bool StreamProcessor::dropFrames(unsigned int nbframes) { 281 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "StreamProcessor::dropFrames(%d)\n", nbframes); 282 return m_data_buffer->dropFrames(nbframes); 276 283 } 277 284 branches/ppalmers-streaming/src/libstreaming/StreamProcessor.h
r494 r703 91 91 virtual bool putFrames(unsigned int nbframes, int64_t ts) = 0; ///< transfer the buffer contents from client 92 92 virtual bool getFrames(unsigned int nbframes, int64_t ts) = 0; ///< transfer the buffer contents to the client 93 virtual bool putFramesDry(unsigned int nbframes, int64_t ts) = 0; ///< dry-process the buffer contents 94 virtual bool getFramesDry(unsigned int nbframes, int64_t ts) = 0; ///< dry-process the buffer contents 93 95 94 96 virtual bool reset(); ///< reset the streams & buffers (e.g. after xrun) … … 149 151 */ 150 152 virtual bool canClientTransferFrames(unsigned int nframes) = 0; 153 154 /** 155 * @brief drop nframes from the internal buffer 156 * 157 * this function drops nframes from the internal buffers, without any 158 * specification on what frames are dropped. Timestamps are not updated. 159 * 160 * @param nframes number of frames 161 * @return true if the operation was successful 162 */ 163 virtual bool dropFrames(unsigned int nframes); 151 164 152 165 /** … … 242 255 {return RAW1394_ISO_STOP;}; 243 256 virtual bool putFrames(unsigned int nbframes, int64_t ts) {return false;}; 257 virtual bool putFramesDry(unsigned int nbframes, int64_t ts) {return false;}; 244 258 245 259 virtual enum raw1394_iso_disposition putPacket(unsigned char *data, unsigned int length, … … 276 290 unsigned int cycle, unsigned int dropped) {return RAW1394_ISO_STOP;}; 277 291 virtual bool getFrames(unsigned int nbframes, int64_t ts) {return false;}; 278 279 virtual enum raw1394_iso_disposition 280 getPacket(unsigned char *data, unsigned int *length, 281 unsigned char *tag, unsigned char *sy, 282 int cycle, unsigned int dropped, unsigned int max_length) = 0; 292 virtual bool getFramesDry(unsigned int nbframes, int64_t ts) {return false;}; 293 283 294 virtual void setVerboseLevel(int l); 284 295 branches/ppalmers-streaming/src/libstreaming/StreamProcessorManager.cpp
r512 r703 173 173 debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 174 174 175 m_isoManager=new IsoHandlerManager(m_thread_realtime, m_thread_priority );175 m_isoManager=new IsoHandlerManager(m_thread_realtime, m_thread_priority + 1); 176 176 177 177 if(!m_isoManager) { … … 296 296 } 297 297 298 // EXPERIMENT:299 // the only stream that should be running is the sync300 // source stream, as this is the one that defines301 // when to signal buffers. Maybe we get an xrun at startup,302 // but that should be handled.303 304 // the problem is that otherwise a setup with a device305 // that waits for decent input before sending output306 // will not start up (e.g. the bounce device), because307 // all streams are required to be running.308 309 // other streams still have at least ENABLE_DELAY_CYCLES cycles310 // to start up311 // if(!m_SyncSource->isRunning()) notRunning=true;312 313 298 usleep(1000); 314 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Running check: %d\n", notRunning);299 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Running check: %d\n", notRunning); 315 300 } 316 301 … … 342 327 // we want to make sure that everything is running well, 343 328 // so wait for a while 344 usleep(USECS_PER_CYCLE * CYCLES_TO_SLEEP_AFTER_RUN_SIGNAL);329 // usleep(USECS_PER_CYCLE * CYCLES_TO_SLEEP_AFTER_RUN_SIGNAL); 345 330 346 331 debugOutput( DEBUG_LEVEL_VERBOSE, " StreamProcessor streams running...\n"); … … 373 358 it != m_ReceiveProcessors.end(); 374 359 ++it ) { 360 // get the receive SP's going at receiving data 361 (*it)->m_data_buffer->setTransparent(false); 375 362 (*it)->reset(); 376 363 } … … 379 366 it != m_TransmitProcessors.end(); 380 367 ++it ) { 368 // make sure the SP retains it's prefilled data 369 (*it)->m_data_buffer->setTransparent(false); 381 370 (*it)->reset(); 382 371 } 383 372 373 dumpInfo(); 374 // All buffers are prefilled and set-up, the only thing 375 // that remains a mistery is the timestamp information. 376 // m_SyncSource->m_data_buffer->setTransparent(false); 377 // debugShowBackLog(); 378 379 debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for sync...\n"); 380 // in order to obtain that, we wait for the first periods to be 381 // received. 382 int nb_sync_runs=10; 383 while(nb_sync_runs--) { // or while not sync-ed? 384 waitForPeriod(); 385 386 // drop the frames for all receive SP's 387 dryRun(StreamProcessor::E_Receive); 388 389 // we don't have to dryrun for the xmit SP's since they 390 // are not sending data yet. 391 } 392 393 debugOutput( DEBUG_LEVEL_VERBOSE, " sync at TS=%011llu...\n", m_time_of_transfer); 394 // FIXME: xruns can screw up the framecounter accounting. do something more sane here 395 resetXrunCounters(); 396 // lock the isohandlermanager such that things freeze 397 // debugShowBackLog(); 398 399 // we now should have decent sync info 400 // the buffers of the receive streams should be (approx) empty 401 // the buffers of the xmit streams should be full 402 403 // note what should the timestamp of the first sample be? 404 405 // at this point the buffer head timestamp of the transmit buffers can be 406 // set properly since we know the sync source's timestamp of the last 407 // buffer transfer. we also know the rate. 408 409 debugOutput( DEBUG_LEVEL_VERBOSE, " propagate sync info...\n"); 410 // FIXME: in the SPM it would be nice to have system time instead of 411 // 1394 time 412 // float rate=m_SyncSource->getTicksPerFrame(); 413 // int64_t one_ringbuffer_in_ticks=(int64_t)(((float)(m_nb_buffers*m_period))*rate); 414 // // the data at the front of the buffer is intended to be transmitted 415 // // nb_periods*period_size after the last received period 416 // int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks); 417 418 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 419 it != m_TransmitProcessors.end(); 420 ++it ) { 421 // FIXME: encapsulate 422 (*it)->m_data_buffer->setBufferHeadTimestamp(m_time_of_transfer); 423 //(*it)->m_data_buffer->setNominalRate(rate); //CHECK!!! 424 } 425 426 dumpInfo(); 427 428 // this is the place were we should be syncing the received streams too 429 // check how much they differ 430 431 384 432 debugOutput( DEBUG_LEVEL_VERBOSE, "Enabling StreamProcessors...\n"); 385 433 … … 387 435 388 436 // FIXME: this should not be in cycles, but in 'time' 437 // FIXME: remove the timestamp 389 438 unsigned int enable_at=TICKS_TO_CYCLES(now)+ENABLE_DELAY_CYCLES; 390 439 if (enable_at > 8000) enable_at -= 8000; … … 395 444 } 396 445 397 return true; 446 debugOutput( DEBUG_LEVEL_VERBOSE, "Running dry for a while...\n"); 447 // run some cycles 'dry' such that everything can stabilize 448 int nb_dryrun_cycles=10; 449 bool no_xrun; 450 while(nb_dryrun_cycles--) { 451 waitForPeriod(); 452 no_xrun = dryRun(); // dry run both receive and xmit 453 454 if (no_xrun) { 455 debugOutput( DEBUG_LEVEL_VERBOSE, " This dry-run was not xrun free...\n" ); 456 resetXrunCounters(); 457 // FIXME: xruns can screw up the framecounter accounting. do something more sane here 458 } 459 } 460 461 // now we should clear the xrun flags 462 resetXrunCounters(); 463 464 // and off we go 465 return true; 466 } 467 468 void StreamProcessorManager::resetXrunCounters(){ 469 debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting xrun flags...\n"); 470 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 471 it != m_ReceiveProcessors.end(); 472 ++it ) 473 { 474 (*it)->resetXrunCounter(); 475 } 476 477 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 478 it != m_TransmitProcessors.end(); 479 ++it ) 480 { 481 (*it)->resetXrunCounter(); 482 } 398 483 } 399 484 … … 492 577 } 493 578 579 debugOutput( DEBUG_LEVEL_VERBOSE, "Disabling StreamProcessors...\n"); 580 if (!disableStreamProcessors()) { 581 debugFatal("Could not disable StreamProcessors...\n"); 582 return false; 583 } 494 584 495 585 debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handlers...\n"); … … 585 675 586 676 // now we wait for the SP's to get enabled 587 debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for all StreamProcessors to be enabled...\n");588 // we have to wait until all streamprocessors indicate that they are running589 // i.e. that there is actually some data stream flowing590 int wait_cycles=ENABLE_TIMEOUT_MSEC; // two seconds591 bool notEnabled=true;592 while (notEnabled && wait_cycles) {593 wait_cycles--;594 notEnabled=false;595 596 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();597 it != m_ReceiveProcessors.end();598 ++it ) {599 if(!(*it)->isEnabled()) notEnabled=true;600 }601 602 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();603 it != m_TransmitProcessors.end();604 ++it ) {605 if(!(*it)->isEnabled()) notEnabled=true;606 }607 usleep(1000); // one cycle608 }609 610 if(!wait_cycles) { // timout has occurred611 debugFatal("One or more streams couldn't be enabled (timeout):\n");612 613 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();614 it != m_ReceiveProcessors.end();615 ++it ) {616 if(!(*it)->isEnabled()) {617 debugFatal(" receive stream %p not enabled\n",*it);618 } else {619 debugFatal(" receive stream %p enabled\n",*it);620 }621 }622 623 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();624 it != m_TransmitProcessors.end();625 ++it ) {626 if(!(*it)->isEnabled()) {627 debugFatal(" transmit stream %p not enabled\n",*it);628 } else {629 debugFatal(" transmit stream %p enabled\n",*it);630 }631 }632 return false;633 }677 // debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for all StreamProcessors to be enabled...\n"); 678 // // we have to wait until all streamprocessors indicate that they are running 679 // // i.e. that there is actually some data stream flowing 680 // int wait_cycles=ENABLE_TIMEOUT_MSEC; // two seconds 681 // bool notEnabled=true; 682 // while (notEnabled && wait_cycles) { 683 // wait_cycles--; 684 // notEnabled=false; 685 // 686 // for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 687 // it != m_ReceiveProcessors.end(); 688 // ++it ) { 689 // if(!(*it)->isEnabled()) notEnabled=true; 690 // } 691 // 692 // for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 693 // it != m_TransmitProcessors.end(); 694 // ++it ) { 695 // if(!(*it)->isEnabled()) notEnabled=true; 696 // } 697 // usleep(1000); // one cycle 698 // } 699 // 700 // if(!wait_cycles) { // timout has occurred 701 // debugFatal("One or more streams couldn't be enabled (timeout):\n"); 702 // 703 // for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 704 // it != m_ReceiveProcessors.end(); 705 // ++it ) { 706 // if(!(*it)->isEnabled()) { 707 // debugFatal(" receive stream %p not enabled\n",*it); 708 // } else { 709 // debugFatal(" receive stream %p enabled\n",*it); 710 // } 711 // } 712 // 713 // for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 714 // it != m_TransmitProcessors.end(); 715 // ++it ) { 716 // if(!(*it)->isEnabled()) { 717 // debugFatal(" transmit stream %p not enabled\n",*it); 718 // } else { 719 // debugFatal(" transmit stream %p enabled\n",*it); 720 // } 721 // } 722 // return false; 723 // } 634 724 635 725 debugOutput( DEBUG_LEVEL_VERBOSE, " => all StreamProcessors enabled...\n"); … … 661 751 ++it ) { 662 752 (*it)->disable(); 753 (*it)->m_data_buffer->setTransparent(true); 663 754 } 664 755 … … 667 758 ++it ) { 668 759 (*it)->disable(); 760 (*it)->m_data_buffer->setTransparent(true); 669 761 } 670 762 … … 833 925 } 834 926 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "XF at %011llu ticks, RBF=%d, XBF=%d, SUM=%d...\n", 835 m_time_of_transfer, rcv_bf,xmt_bf,rcv_bf+xmt_bf);927 m_time_of_transfer, rcv_bf, xmt_bf, rcv_bf+xmt_bf); 836 928 837 929 #endif … … 925 1017 int64_t one_frame_in_ticks=(int64_t)(((float)m_period)*rate); 926 1018 927 int64_t receive_timestamp = substractTicks(m_time_of_transfer, one_frame_in_ticks);1019 int64_t receive_timestamp = substractTicks(m_time_of_transfer, one_frame_in_ticks); 928 1020 929 1021 if(receive_timestamp<0) { … … 951 1043 it != m_TransmitProcessors.end(); 952 1044 ++it ) { 953 954 if(!(*it)->putFrames(m_period, (int64_t)m_time_of_transfer)) { 1045 // FIXME: in the SPM it would be nice to have system time instead of 1046 // 1394 time 1047 float rate=m_SyncSource->getTicksPerFrame(); 1048 int64_t one_ringbuffer_in_ticks=(int64_t)(((float)(m_nb_buffers*m_period))*rate); 1049 1050 // the data we are putting into the buffer is intended to be transmitted 1051 // one ringbuffer size after it has been received 1052 int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks); 1053 1054 if(!(*it)->putFrames(m_period, transmit_timestamp)) { 955 1055 debugOutput(DEBUG_LEVEL_VERBOSE, "could not putFrames(%u,%llu) to stream processor (%p)\n", 956 m_period, m_time_of_transfer, *it); 1056 m_period, transmit_timestamp, *it); 1057 return false; // buffer overrun 1058 } 1059 1060 } 1061 } 1062 1063 return true; 1064 } 1065 1066 /** 1067 * @brief Dry run one period for both receive and transmit StreamProcessors 1068 * 1069 * Process one period of frames for all streamprocessors, without touching the 1070 * client buffers. This only removes an incoming period from the ISO receive buffer and 1071 * puts one period of silence into the transmit buffers. 1072 * 1073 * @return true if successful, false otherwise (indicates xrun). 1074 */ 1075 bool StreamProcessorManager::dryRun() { 1076 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Dry-running period...\n"); 1077 if (!dryRun(StreamProcessor::E_Receive)) return false; 1078 if (!dryRun(StreamProcessor::E_Transmit)) return false; 1079 return true; 1080 } 1081 1082 /** 1083 * @brief Dry run one period for either the receive or transmit StreamProcessors 1084 * 1085 * see dryRun() 1086 * 1087 * @param t The processor type to dryRun for (receive or transmit) 1088 * @return true if successful, false otherwise (indicates xrun). 1089 */ 1090 1091 bool StreamProcessorManager::dryRun(enum StreamProcessor::EProcessorType t) { 1092 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 1093 1094 // a static cast could make sure that there is no performance 1095 // penalty for the virtual functions (to be checked) 1096 if (t==StreamProcessor::E_Receive) { 1097 1098 // determine the time at which we want reception to start 1099 float rate=m_SyncSource->getTicksPerFrame(); 1100 int64_t one_frame_in_ticks=(int64_t)(((float)m_period)*rate); 1101 1102 int64_t receive_timestamp = substractTicks(m_time_of_transfer, one_frame_in_ticks); 1103 1104 if(receive_timestamp<0) { 1105 debugWarning("receive ts < 0.0 : %lld, m_time_of_transfer= %llu, one_frame_in_ticks=%lld\n", 1106 receive_timestamp, m_time_of_transfer, one_frame_in_ticks); 1107 } 1108 if(receive_timestamp>(128L*TICKS_PER_SECOND)) { 1109 debugWarning("receive ts > 128L*TICKS_PER_SECOND : %lld, m_time_of_transfer= %llu, one_frame_in_ticks=%lld\n", 1110 receive_timestamp, m_time_of_transfer, one_frame_in_ticks); 1111 } 1112 1113 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 1114 it != m_ReceiveProcessors.end(); 1115 ++it ) { 1116 1117 if(!(*it)->getFramesDry(m_period, receive_timestamp)) { 1118 debugOutput(DEBUG_LEVEL_VERBOSE,"could not getFrames(%u, %11llu) from stream processor (%p)\n", 1119 m_period, m_time_of_transfer,*it); 1120 return false; // buffer underrun 1121 } 1122 1123 } 1124 } else { 1125 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 1126 it != m_TransmitProcessors.end(); 1127 ++it ) { 1128 // FIXME: in the SPM it would be nice to have system time instead of 1129 // 1394 time 1130 float rate=m_SyncSource->getTicksPerFrame(); 1131 int64_t one_ringbuffer_in_ticks=(int64_t)(((float)(m_nb_buffers*m_period))*rate); 1132 1133 // the data we are putting into the buffer is intended to be transmitted 1134 // one ringbuffer size after it has been received 1135 int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks); 1136 1137 if(!(*it)->putFramesDry(m_period, transmit_timestamp)) { 1138 debugOutput(DEBUG_LEVEL_VERBOSE, "could not putFrames(%u,%llu) to stream processor (%p)\n", 1139 m_period, transmit_timestamp, *it); 957 1140 return false; // buffer overrun 958 1141 } branches/ppalmers-streaming/src/libstreaming/StreamProcessorManager.h
r445 r703 87 87 bool transfer(); ///< transfer the buffer contents from/to client 88 88 bool transfer(enum StreamProcessor::EProcessorType); ///< transfer the buffer contents from/to client (single processor type) 89 90 bool dryRun(); 91 bool dryRun(enum StreamProcessor::EProcessorType); 89 92 90 93 int getDelayedUsecs() {return m_delayed_usecs;}; … … 93 96 94 97 private: 98 void resetXrunCounters(); 99 95 100 int m_delayed_usecs; 96 101 // this stores the time at which the next transfer should occur