101 | | // The MOTU transmit stream is 'always' ready |
---|
102 | | m_running = true; |
---|
103 | | |
---|
104 | | // Initialise the cycle timer if this is the first time |
---|
105 | | // iso data has been requested. |
---|
106 | | if (!m_disabled && m_cycle_count<0) { |
---|
107 | | m_cycle_count = cycle; |
---|
108 | | m_cycle_ofs = 0.0; |
---|
109 | | } |
---|
110 | | |
---|
111 | | // Similarly, initialise the "next cycle". This can be done |
---|
112 | | // whenever iso data is seen - it doesn't have to wait until |
---|
113 | | // the stream is enabled. |
---|
114 | | if (m_next_cycle < 0) |
---|
115 | | m_next_cycle = cycle; |
---|
| 119 | // as long as the cycle parameter is not in sync with |
---|
| 120 | // the current time, the stream is considered not |
---|
| 121 | // to be 'running' |
---|
| 122 | // NOTE: this works only at startup |
---|
| 123 | if (!m_running && cycle_diff >= 0 && cycle != -1) { |
---|
| 124 | debugOutput(DEBUG_LEVEL_VERBOSE, "Xmit StreamProcessor %p started running at cycle %d\n",this, cycle); |
---|
| 125 | m_running=true; |
---|
| 126 | } |
---|
| 127 | |
---|
| 128 | if (!m_disabled && m_is_disabled) { |
---|
| 129 | // this means that we are trying to enable |
---|
| 130 | if ((unsigned int)cycle == m_cycle_to_enable_at) { |
---|
| 131 | m_is_disabled=false; |
---|
| 132 | |
---|
| 133 | debugOutput(DEBUG_LEVEL_VERBOSE,"Enabling StreamProcessor %p at %u\n", this, cycle); |
---|
| 134 | |
---|
| 135 | // initialize the buffer head & tail |
---|
| 136 | m_SyncSource->m_data_buffer->getBufferHeadTimestamp(&ts_head, &fc); // thread safe |
---|
| 137 | |
---|
| 138 | // the number of cycles the sync source lags (> 0) |
---|
| 139 | // or leads (< 0) |
---|
| 140 | int sync_lag_cycles=substractCycles(cycle, m_SyncSource->getLastCycle()); |
---|
| 141 | |
---|
| 142 | // account for the cycle lag between sync SP and this SP |
---|
| 143 | // the last update of the sync source's timestamps was sync_lag_cycles |
---|
| 144 | // cycles before the cycle we are calculating the timestamp for. |
---|
| 145 | // if we were to use one-frame buffers, you would expect the |
---|
| 146 | // frame that is sent on cycle CT to have a timestamp T1. |
---|
| 147 | // ts_head however is for cycle CT-sync_lag_cycles, and lies |
---|
| 148 | // therefore sync_lag_cycles * TICKS_PER_CYCLE earlier than |
---|
| 149 | // T1. |
---|
| 150 | ts_head = addTicks(ts_head, sync_lag_cycles * TICKS_PER_CYCLE); |
---|
| 151 | |
---|
| 152 | m_data_buffer->setBufferTailTimestamp(ts_head); |
---|
| 153 | |
---|
| 154 | #ifdef DEBUG |
---|
| 155 | if ((unsigned int)m_data_buffer->getFrameCounter() != m_data_buffer->getBufferSize()) { |
---|
| 156 | debugWarning("m_data_buffer->getFrameCounter() != m_data_buffer->getBufferSize()\n"); |
---|
| 157 | } |
---|
| 158 | #endif |
---|
| 159 | debugOutput(DEBUG_LEVEL_VERBOSE,"XMIT TS SET: TS=%10lld, LAG=%03d, FC=%4d\n", |
---|
| 160 | ts_head, sync_lag_cycles, m_data_buffer->getFrameCounter()); |
---|
| 161 | } else { |
---|
| 162 | debugOutput(DEBUG_LEVEL_VERY_VERBOSE, |
---|
| 163 | "will enable StreamProcessor %p at %u, now is %d\n", |
---|
| 164 | this, m_cycle_to_enable_at, cycle); |
---|
| 165 | } |
---|
| 166 | } else if (m_disabled && !m_is_disabled) { |
---|
| 167 | // trying to disable |
---|
| 168 | debugOutput(DEBUG_LEVEL_VERBOSE,"disabling StreamProcessor %p at %u\n", |
---|
| 169 | this, cycle); |
---|
| 170 | m_is_disabled=true; |
---|
| 171 | } |
---|
122 | | debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); |
---|
123 | | |
---|
| 178 | |
---|
| 179 | // the base timestamp is the one of the next sample in the buffer |
---|
| 180 | m_data_buffer->getBufferHeadTimestamp(&ts_head, &fc); // thread safe |
---|
| 181 | |
---|
| 182 | int64_t timestamp = ts_head; |
---|
| 183 | |
---|
| 184 | // we send a packet some cycles in advance, to avoid the |
---|
| 185 | // following situation: |
---|
| 186 | // suppose we are only a few ticks away from |
---|
| 187 | // the moment to send this packet. therefore we decide |
---|
| 188 | // not to send the packet, but send it in the next cycle. |
---|
| 189 | // This means that the next time point will be 3072 ticks |
---|
| 190 | // later, making that the timestamp will be expired when the |
---|
| 191 | // packet is sent, unless TRANSFER_DELAY > 3072. |
---|
| 192 | // this means that we need at least one cycle of extra buffering. |
---|
| 193 | uint64_t ticks_to_advance = TICKS_PER_CYCLE * TRANSMIT_ADVANCE_CYCLES; |
---|
| 194 | |
---|
| 195 | // if cycle lies cycle_diff cycles in the future, we should |
---|
| 196 | // queue this packet cycle_diff * TICKS_PER_CYCLE earlier than |
---|
| 197 | // we would if it were to be sent immediately. |
---|
| 198 | ticks_to_advance += cycle_diff * TICKS_PER_CYCLE; |
---|
| 199 | |
---|
| 200 | // determine the 'now' time in ticks |
---|
| 201 | uint64_t cycle_timer=CYCLE_TIMER_TO_TICKS(ctr); |
---|
| 202 | |
---|
| 203 | // time until the packet is to be sent (if > 0: send packet) |
---|
| 204 | int64_t until_next=substractTicks(timestamp, cycle_timer + ticks_to_advance); |
---|
| 205 | |
---|
| 208 | |
---|
| 209 | // don't process the stream when it is not enabled, not running |
---|
| 210 | // or when the next sample is not due yet. |
---|
| 211 | if((until_next>0) || m_is_disabled || !m_running) { |
---|
| 212 | // send dummy packet |
---|
| 213 | |
---|
| 214 | // construct the packet CIP-like header. Even if this is a data-less |
---|
| 215 | // packet the dbs field is still set as if there were data blocks |
---|
| 216 | // present. For data-less packets the dbc is the same as the previously |
---|
| 217 | // transmitted block. |
---|
| 218 | *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); |
---|
| 219 | quadlet++; |
---|
| 220 | *quadlet = htonl(0x8222ffff); |
---|
| 221 | quadlet++; |
---|
| 222 | *length = 8; |
---|
| 223 | |
---|
| 224 | #warning high-pitched sound protection removed! |
---|
| 225 | // In the disabled state simply zero all data sent to the MOTU. If |
---|
| 226 | // a stream of empty packets are sent once iso streaming is enabled |
---|
| 227 | // the MOTU tends to emit high-pitched audio (approx 10 kHz) for |
---|
| 228 | // some reason. This is not completely sufficient, however (zeroed |
---|
| 229 | // packets must also be sent on iso closedown). |
---|
| 230 | |
---|
| 231 | // FIXME: Currently we simply send empty packets to the MOTU when |
---|
| 232 | // the stream is disabled so the "m_disabled == 0" code is never |
---|
| 233 | // executed. However, this may change in future so it's left in |
---|
| 234 | // for the moment for reference. |
---|
| 235 | // FIXME: Currently we don't read the buffer at all during closedown. |
---|
| 236 | // We could (and silently junk the contents) if it turned out to be |
---|
| 237 | // more helpful. |
---|
| 238 | |
---|
| 239 | return RAW1394_ISO_DEFER; |
---|
| 240 | } |
---|
132 | | // Size of data to read from the event buffer, in bytes. |
---|
133 | | unsigned int read_size = n_events * m_event_size; |
---|
134 | | |
---|
135 | | // Detect a missed cycle and attempt to "catch up". |
---|
136 | | if (cycle != m_next_cycle) { |
---|
137 | | debugOutput(DEBUG_LEVEL_VERBOSE, "tx cycle miss: %d requested, %d expected\n",cycle,m_next_cycle); |
---|
138 | | } |
---|
139 | | // Attempt to catch up any missed cycles but only if we're enabled. |
---|
140 | | if (!m_disabled && cycle!=m_next_cycle) { |
---|
141 | | float ftmp; |
---|
142 | | signed int ccount = m_next_cycle; |
---|
143 | | |
---|
144 | | while (ccount!=cycle) { |
---|
145 | | unwrapped_cycle = ccount; |
---|
146 | | if (m_cycle_count-ccount > 7900) |
---|
147 | | unwrapped_cycle += 8000; |
---|
148 | | |
---|
149 | | if (unwrapped_cycle < m_cycle_count) { |
---|
150 | | if (++ccount == 8000) |
---|
151 | | ccount = 0; |
---|
152 | | continue; |
---|
153 | | } |
---|
154 | | // Advance buffers and counters as if this cycle had been dealt with |
---|
155 | | m_tx_dbc += n_events; |
---|
156 | | incrementFrameCounter(n_events); |
---|
157 | | |
---|
158 | | ftmp = m_cycle_ofs+n_events*(*m_ticks_per_frame); |
---|
159 | | m_cycle_count += (unsigned int)ftmp/3072; |
---|
160 | | m_cycle_count %= 8000; |
---|
161 | | m_cycle_ofs = fmod(ftmp, 3072); |
---|
162 | | |
---|
163 | | if (++ccount == 8000) |
---|
164 | | ccount = 0; |
---|
165 | | |
---|
166 | | // Also advance the event buffer to keep things in sync |
---|
167 | | freebob_ringbuffer_read_advance(m_event_buffer,read_size); |
---|
168 | | } |
---|
169 | | m_tx_dbc &= 0xff; |
---|
170 | | debugOutput(DEBUG_LEVEL_VERBOSE, " resuming with cyclecount=%d, cycleofs=%g (ticksperfame=%g)\n", |
---|
171 | | m_cycle_count, m_cycle_ofs, *m_ticks_per_frame); |
---|
172 | | |
---|
173 | | m_next_cycle = cycle; |
---|
174 | | } |
---|
175 | | |
---|
176 | | if ((m_next_cycle=cycle+1) >= 8000) |
---|
177 | | m_next_cycle -= 8000; |
---|
178 | | |
---|
179 | | // Deal cleanly with potential wrap-around cycle timer conditions |
---|
180 | | unwrapped_cycle = cycle; |
---|
181 | | if (m_cycle_count-cycle > 7900) |
---|
182 | | unwrapped_cycle += 8000; |
---|
183 | | |
---|
184 | | // Increment the dbc (data block count). This is only done if the |
---|
185 | | // packet will contain events - that is, we are due to send some |
---|
186 | | // data. Otherwise a pad packet is sent which contains the DBC of |
---|
187 | | // the previously sent packet. This regime also means that the very |
---|
188 | | // first packet containing data will have a DBC of n_events, which |
---|
189 | | // matches what is observed from other systems. |
---|
190 | | if (!m_disabled && unwrapped_cycle>=m_cycle_count) { |
---|
191 | | m_tx_dbc += n_events; |
---|
192 | | if (m_tx_dbc > 0xff) |
---|
193 | | m_tx_dbc -= 0x100; |
---|
194 | | } |
---|
195 | | |
---|
196 | | // construct the packet CIP-like header. Even if this is a data-less |
---|
197 | | // packet the dbs field is still set as if there were data blocks |
---|
198 | | // present. For data-less packets the dbc is the same as the previously |
---|
199 | | // transmitted block. |
---|
200 | | *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); |
---|
201 | | quadlet++; |
---|
202 | | *quadlet = htonl(0x8222ffff); |
---|
203 | | quadlet++; |
---|
204 | | *length = 8; |
---|
205 | | |
---|
206 | | // If the stream is disabled or the MOTU transmission cycle count is |
---|
207 | | // ahead of the ieee1394 cycle timer, we send a data-less packet |
---|
208 | | // with only the 8 byte CIP-like header set up previously. |
---|
209 | | if (m_disabled || unwrapped_cycle<m_cycle_count) { |
---|
210 | | return RAW1394_ISO_OK; |
---|
211 | | } |
---|
212 | | |
---|
213 | | // In the disabled state simply zero all data sent to the MOTU. If |
---|
214 | | // a stream of empty packets are sent once iso streaming is enabled |
---|
215 | | // the MOTU tends to emit high-pitched audio (approx 10 kHz) for |
---|
216 | | // some reason. This is not completely sufficient, however (zeroed |
---|
217 | | // packets must also be sent on iso closedown). |
---|
218 | | |
---|
219 | | // FIXME: Currently we simply send empty packets to the MOTU when |
---|
220 | | // the stream is disabled so the "m_disabled == 0" code is never |
---|
221 | | // executed. However, this may change in future so it's left in |
---|
222 | | // for the moment for reference. |
---|
223 | | // FIXME: Currently we don't read the buffer at all during closedown. |
---|
224 | | // We could (and silently junk the contents) if it turned out to be |
---|
225 | | // more helpful. |
---|
226 | | if (!m_disabled && m_closedown_count<0) { |
---|
227 | | // We read the packet data from a ringbuffer because of |
---|
228 | | // efficiency; it allows us to construct the packets one |
---|
229 | | // period at once. |
---|
230 | | i = freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size) < |
---|
231 | | read_size; |
---|
232 | | } else { |
---|
233 | | memset(data+8, 0, read_size); |
---|
234 | | i = 0; |
---|
235 | | } |
---|
236 | | if (i == 1) { |
---|
237 | | /* there is no more data in the ringbuffer */ |
---|
238 | | debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n", |
---|
239 | | cycle, m_framecounter, m_handler->getPacketCount()); |
---|
240 | | |
---|
241 | | // signal underrun |
---|
242 | | m_xruns++; |
---|
243 | | |
---|
244 | | retval=RAW1394_ISO_DEFER; // make raw1394_loop_iterate exit its inner loop |
---|
245 | | n_events = 0; |
---|
246 | | |
---|
247 | | } else { |
---|
248 | | |
---|
249 | | retval=RAW1394_ISO_OK; |
---|
250 | | *length += read_size; |
---|
251 | | |
---|
| 247 | // add the transmit transfer delay to construct the playout time |
---|
| 248 | uint64_t ts=addTicks(timestamp, TRANSMIT_TRANSFER_DELAY); |
---|
| 249 | |
---|
| 250 | if (m_data_buffer->readFrames(n_events, (char *)(data + 8))) { |
---|
| 251 | |
---|
| 252 | // Increment the dbc (data block count). This is only done if the |
---|
| 253 | // packet will contain events - that is, we are due to send some |
---|
| 254 | // data. Otherwise a pad packet is sent which contains the DBC of |
---|
| 255 | // the previously sent packet. This regime also means that the very |
---|
| 256 | // first packet containing data will have a DBC of n_events, which |
---|
| 257 | // matches what is observed from other systems. |
---|
| 258 | m_tx_dbc += n_events; |
---|
| 259 | if (m_tx_dbc > 0xff) |
---|
| 260 | m_tx_dbc -= 0x100; |
---|
| 261 | |
---|
| 262 | // construct the packet CIP-like header. Even if this is a data-less |
---|
| 263 | // packet the dbs field is still set as if there were data blocks |
---|
| 264 | // present. For data-less packets the dbc is the same as the previously |
---|
| 265 | // transmitted block. |
---|
| 266 | *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); |
---|
| 267 | quadlet++; |
---|
| 268 | *quadlet = htonl(0x8222ffff); |
---|
| 269 | quadlet++; |
---|
| 270 | |
---|
| 271 | *length = n_events*m_event_size + 8; |
---|
| 272 | |
---|
| 273 | // convert the timestamp to Motu format |
---|
| 274 | // I assume that it is in ticks, and wraps as the cycle timer |
---|
| 275 | #warning syt conversion to be done |
---|
| 276 | |
---|
320 | | } |
---|
321 | | |
---|
322 | | // Update the frame counter |
---|
323 | | incrementFrameCounter(n_events); |
---|
324 | | |
---|
325 | | // Keep this at the end, because otherwise the raw1394_loop_iterate |
---|
326 | | // functions inner loop keeps requesting packets, that are not |
---|
327 | | // nescessarily ready |
---|
328 | | |
---|
329 | | // Amdtp has this commented out |
---|
330 | | if (m_framecounter > (signed int)m_period) { |
---|
331 | | retval=RAW1394_ISO_DEFER; |
---|
332 | | } |
---|
333 | | |
---|
334 | | return retval; |
---|
335 | | } |
---|
336 | | |
---|
337 | | bool MotuTransmitStreamProcessor::isOnePeriodReady() { |
---|
338 | | // TODO: this is the way you can implement sync |
---|
339 | | // only when this returns true, one period will be |
---|
340 | | // transferred to the audio api side. |
---|
341 | | // you can delay this moment as long as you |
---|
342 | | // want (provided that there is enough buffer space) |
---|
343 | | |
---|
344 | | // this implementation just waits until there is one period of samples |
---|
345 | | // transmitted from the buffer |
---|
346 | | |
---|
347 | | // Amdtp has this commented out and simply return true. |
---|
348 | | return (m_framecounter > (signed int)m_period); |
---|
349 | | // return true; |
---|
350 | | } |
---|
351 | | |
---|
| 304 | |
---|
| 305 | return RAW1394_ISO_OK; |
---|
| 306 | |
---|
| 307 | } else if (now_cycles<cycle) { |
---|
| 308 | // we can still postpone the queueing of the packets |
---|
| 309 | return RAW1394_ISO_AGAIN; |
---|
| 310 | } else { // there is no more data in the ringbuffer |
---|
| 311 | |
---|
| 312 | debugWarning("Transmit buffer underrun (now %d, queue %d, target %d)\n", |
---|
| 313 | now_cycles, cycle, TICKS_TO_CYCLES(ts)); |
---|
| 314 | |
---|
| 315 | // signal underrun |
---|
| 316 | m_xruns++; |
---|
| 317 | |
---|
| 318 | // disable the processing, will be re-enabled when |
---|
| 319 | // the xrun is handled |
---|
| 320 | m_disabled=true; |
---|
| 321 | m_is_disabled=true; |
---|
| 322 | |
---|
| 323 | // compose a no-data packet, we should always |
---|
| 324 | // send a valid packet |
---|
| 325 | |
---|
| 326 | // send dummy packet |
---|
| 327 | |
---|
| 328 | // construct the packet CIP-like header. Even if this is a data-less |
---|
| 329 | // packet the dbs field is still set as if there were data blocks |
---|
| 330 | // present. For data-less packets the dbc is the same as the previously |
---|
| 331 | // transmitted block. |
---|
| 332 | *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); |
---|
| 333 | quadlet++; |
---|
| 334 | *quadlet = htonl(0x8222ffff); |
---|
| 335 | quadlet++; |
---|
| 336 | *length = 8; |
---|
| 337 | |
---|
| 338 | return RAW1394_ISO_DEFER; |
---|
| 339 | } |
---|
| 340 | |
---|
| 341 | // we shouldn't get here |
---|
| 342 | return RAW1394_ISO_ERROR; |
---|
| 343 | |
---|
| 344 | } |
---|
| 345 | |
---|
| 346 | int MotuTransmitStreamProcessor::getMinimalSyncDelay() { |
---|
| 347 | return 0; |
---|
| 348 | } |
---|
| 349 | |
---|
408 | | |
---|
409 | | if( !(m_event_buffer=freebob_ringbuffer_create( |
---|
410 | | m_event_size * ringbuffer_size_frames))) { |
---|
411 | | debugFatal("Could not allocate memory event ringbuffer"); |
---|
412 | | return false; |
---|
413 | | } |
---|
414 | | |
---|
415 | | // Allocate the temporary event buffer. This is needed for the |
---|
416 | | // efficient transfer() routine. Its size has to be equal to one |
---|
417 | | // 'event'. |
---|
418 | | if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) { |
---|
419 | | debugFatal("Could not allocate temporary event buffer"); |
---|
420 | | freebob_ringbuffer_free(m_event_buffer); |
---|
421 | | return false; |
---|
422 | | } |
---|
| 413 | |
---|
| 414 | // allocate the internal buffer |
---|
| 415 | float ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate); |
---|
| 416 | unsigned int events_per_frame = m_framerate<=48000?8:(m_framerate<=96000?16:32); |
---|
| 417 | |
---|
| 418 | assert(m_data_buffer); |
---|
| 419 | m_data_buffer->setBufferSize(ringbuffer_size_frames); |
---|
| 420 | m_data_buffer->setEventSize(m_event_size/events_per_frame); |
---|
| 421 | m_data_buffer->setEventsPerFrame(events_per_frame); |
---|
| 422 | |
---|
| 423 | m_data_buffer->setUpdatePeriod(m_period); |
---|
| 424 | m_data_buffer->setNominalRate(ticks_per_frame); |
---|
| 425 | |
---|
| 426 | // FIXME: check if the timestamp wraps at one second |
---|
| 427 | m_data_buffer->setWrapValue(TICKS_PER_SECOND); |
---|
| 428 | |
---|
| 429 | m_data_buffer->prepare(); |
---|
| 495 | bool MotuTransmitStreamProcessor::prepareForStop() { |
---|
| 496 | |
---|
| 497 | // If the stream is disabled or isn't running there's no need to |
---|
| 498 | // wait since the MOTU *should* still be in a "zero data" state. |
---|
| 499 | // |
---|
| 500 | // If the m_streaming_active flag is 0 it indicates that the |
---|
| 501 | // transmit callback hasn't been called since a closedown was |
---|
| 502 | // requested when this function was last called. This effectively |
---|
| 503 | // signifies that the streaming thread has been exitted due to an |
---|
| 504 | // xrun in either the receive or transmit handlers. In this case |
---|
| 505 | // there's no point in waiting for the closedown count to hit zero |
---|
| 506 | // because it never will; the zero data will never get to the MOTU. |
---|
| 507 | // It's best to allow an immediate stop and let the xrun handler |
---|
| 508 | // proceed as best it can. |
---|
| 509 | // |
---|
| 510 | // The ability to detect the lack of streaming also prevents the |
---|
| 511 | // "wait for stop" in the stream processor manager's stop() method |
---|
| 512 | // from hitting its timeout which in turn seems to increase the |
---|
| 513 | // probability of a successful recovery. |
---|
| 514 | if (m_is_disabled || !isRunning() || !m_streaming_active) |
---|
| 515 | return true; |
---|
| 516 | |
---|
| 517 | if (m_closedown_count < 0) { |
---|
| 518 | // No closedown has been initiated, so start one now. Set |
---|
| 519 | // the closedown count to the number of zero packets which |
---|
| 520 | // will be sent to the MOTU before closing off the iso |
---|
| 521 | // streams. FIXME: 128 packets (each containing 8 frames at |
---|
| 522 | // 48 kHz) is the experimentally-determined figure for 48 |
---|
| 523 | // kHz with a period size of 1024. It seems that at least |
---|
| 524 | // one period of zero samples need to be sent to allow for |
---|
| 525 | // inter-thread communication occuring on period boundaries. |
---|
| 526 | // This needs to be confirmed for other rates and period |
---|
| 527 | // sizes. |
---|
| 528 | signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32); |
---|
| 529 | m_closedown_count = m_period / n_events; |
---|
| 530 | |
---|
| 531 | // Set up a test to confirm that streaming is still active. |
---|
| 532 | // If the streaming function hasn't been called by the next |
---|
| 533 | // iteration through this function there's no point in |
---|
| 534 | // continuing since it means the zero data will never get to |
---|
| 535 | // the MOTU. |
---|
| 536 | m_streaming_active = 0; |
---|
| 537 | return false; |
---|
| 538 | } |
---|
| 539 | |
---|
| 540 | // We are "go" for closedown once all requested zero packets |
---|
| 541 | // (initiated by a previous call to this function) have been sent to |
---|
| 542 | // the MOTU. |
---|
| 543 | return m_closedown_count == 0; |
---|
| 544 | } |
---|
| 545 | |
---|
| 546 | bool MotuTransmitStreamProcessor::prepareForStart() { |
---|
| 547 | // Reset some critical variables required so the stream starts cleanly. This |
---|
| 548 | // method is called once on every stream restart. Initialisations which should |
---|
| 549 | // be done once should be placed in the init() method instead. |
---|
| 550 | m_running = 0; |
---|
| 551 | m_closedown_count = -1; |
---|
| 552 | m_streaming_active = 0; |
---|
| 553 | |
---|
| 554 | // At this point we'll also disable the stream processor here. |
---|
| 555 | // At this stage stream processors are always explicitly re-enabled |
---|
| 556 | // after being started, so by starting in the disabled state we |
---|
| 557 | // ensure that every start will be exactly the same. |
---|
| 558 | disable(); |
---|
| 559 | |
---|
| 560 | return true; |
---|
| 561 | } |
---|
| 562 | |
---|
| 563 | bool MotuTransmitStreamProcessor::prepareForEnable(uint64_t time_to_enable_at) { |
---|
| 564 | |
---|
| 565 | debugOutput(DEBUG_LEVEL_VERBOSE,"Preparing to enable...\n"); |
---|
| 566 | |
---|
| 567 | // for the transmit SP, we have to initialize the |
---|
| 568 | // buffer timestamp to something sane, because this timestamp |
---|
| 569 | // is used when it is SyncSource |
---|
| 570 | |
---|
| 571 | // the time we initialize to will determine the time at which |
---|
| 572 | // the first sample in the buffer will be sent, so we should |
---|
| 573 | // make it at least 'time_to_enable_at' |
---|
| 574 | |
---|
| 575 | uint64_t now=m_handler->getCycleTimer(); |
---|
| 576 | unsigned int now_secs=CYCLE_TIMER_GET_SECS(now); |
---|
| 577 | |
---|
| 578 | // check if a wraparound on the secs will happen between |
---|
| 579 | // now and the time we start |
---|
| 580 | if (CYCLE_TIMER_GET_CYCLES(now)>time_to_enable_at) { |
---|
| 581 | // the start will happen in the next second |
---|
| 582 | now_secs++; |
---|
| 583 | if (now_secs>=128) now_secs=0; |
---|
| 584 | } |
---|
| 585 | |
---|
| 586 | uint64_t ts_head= now_secs*TICKS_PER_SECOND; |
---|
| 587 | ts_head+=time_to_enable_at*TICKS_PER_CYCLE; |
---|
| 588 | |
---|
| 589 | // we also add the nb of cycles we transmit in advance |
---|
| 590 | ts_head=addTicks(ts_head, TRANSMIT_ADVANCE_CYCLES*TICKS_PER_CYCLE); |
---|
| 591 | |
---|
| 592 | m_data_buffer->setBufferTailTimestamp(ts_head); |
---|
| 593 | |
---|
| 594 | |
---|
| 595 | if (!StreamProcessor::prepareForEnable(time_to_enable_at)) { |
---|
| 596 | debugError("StreamProcessor::prepareForEnable failed\n"); |
---|
| 597 | return false; |
---|
| 598 | } |
---|
| 599 | |
---|
| 600 | return true; |
---|
| 601 | } |
---|
| 602 | |
---|
508 | | return true; |
---|
509 | | } |
---|
510 | | |
---|
511 | | /** |
---|
512 | | * \brief write events queued for transmission from the port ringbuffers |
---|
513 | | * to the event buffer. |
---|
514 | | */ |
---|
515 | | bool MotuTransmitStreamProcessor::transfer() { |
---|
516 | | m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/m_event_size); |
---|
517 | | |
---|
518 | | debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); |
---|
519 | | // TODO: improve |
---|
520 | | /* a naive implementation would look like this: |
---|
521 | | |
---|
522 | | unsigned int write_size=m_period*m_event_size; |
---|
523 | | char *dummybuffer=(char *)calloc(m_period,m_event_size); |
---|
524 | | |
---|
525 | | transmitBlock(dummybuffer, m_period, 0, 0); |
---|
526 | | |
---|
527 | | if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { |
---|
528 | | debugWarning("Could not write to event buffer\n"); |
---|
529 | | } |
---|
530 | | |
---|
531 | | free(dummybuffer); |
---|
532 | | */ |
---|
533 | | /* but we're not that naive anymore... */ |
---|
534 | | int xrun; |
---|
535 | | unsigned int offset=0; |
---|
536 | | |
---|
537 | | freebob_ringbuffer_data_t vec[2]; |
---|
538 | | // There is one period of frames to transfer. This is |
---|
539 | | // period_size*m_event_size of events. |
---|
540 | | unsigned int bytes2write=m_period*m_event_size; |
---|
541 | | |
---|
542 | | /* Write bytes2write bytes to the event ringbuffer. First see if it can |
---|
543 | | * be done in one write; if so, ok. |
---|
544 | | * Otherwise write up to a multiple of events directly to the buffer |
---|
545 | | * then do the buffer wrap around using ringbuffer_write. Then |
---|
546 | | * write the remaining data directly to the buffer in a third pass. |
---|
547 | | * Make sure that we cannot end up on a non-cluster aligned |
---|
548 | | * position! |
---|
549 | | */ |
---|
550 | | while(bytes2write>0) { |
---|
551 | | int byteswritten=0; |
---|
552 | | |
---|
553 | | unsigned int frameswritten=(m_period*m_event_size-bytes2write)/m_event_size; |
---|
554 | | offset=frameswritten; |
---|
555 | | |
---|
556 | | freebob_ringbuffer_get_write_vector(m_event_buffer, vec); |
---|
557 | | |
---|
558 | | if (vec[0].len==0) { // this indicates a full event buffer |
---|
559 | | debugError("XMT: Event buffer overrun in processor %p\n",this); |
---|
560 | | break; |
---|
561 | | } |
---|
562 | | |
---|
563 | | /* If we don't take care we will get stuck in an infinite |
---|
564 | | * loop because we align to a event boundary later. The |
---|
565 | | * remaining nb of bytes in one write operation can be |
---|
566 | | * smaller than one event; this can happen because the |
---|
567 | | * ringbuffer size is always a power of 2. |
---|
568 | | */ |
---|
569 | | if(vec[0].len<m_event_size) { |
---|
570 | | |
---|
571 | | // encode to the temporary buffer |
---|
572 | | xrun = transmitBlock(m_tmp_event_buffer, 1, offset); |
---|
573 | | |
---|
574 | | if (xrun<0) { |
---|
575 | | // xrun detected |
---|
576 | | debugError("XMT: Frame buffer underrun in processor %p\n",this); |
---|
577 | | break; |
---|
578 | | } |
---|
579 | | |
---|
580 | | // Use the ringbuffer function to write one event. |
---|
581 | | // The write function handles the wrap around. |
---|
582 | | freebob_ringbuffer_write(m_event_buffer, |
---|
583 | | m_tmp_event_buffer, m_event_size); |
---|
584 | | |
---|
585 | | // we advanced one m_event_size |
---|
586 | | bytes2write-=m_event_size; |
---|
587 | | |
---|
588 | | } else { |
---|
589 | | |
---|
590 | | if (bytes2write>vec[0].len) { |
---|
591 | | // align to an event boundary |
---|
592 | | byteswritten=vec[0].len-(vec[0].len%m_event_size); |
---|
593 | | } else { |
---|
594 | | byteswritten=bytes2write; |
---|
595 | | } |
---|
596 | | |
---|
597 | | xrun = transmitBlock(vec[0].buf, |
---|
598 | | byteswritten/m_event_size, offset); |
---|
599 | | |
---|
600 | | if (xrun<0) { |
---|
601 | | // xrun detected |
---|
602 | | debugError("XMT: Frame buffer underrun in processor %p\n",this); |
---|
603 | | break; |
---|
604 | | } |
---|
605 | | |
---|
606 | | freebob_ringbuffer_write_advance(m_event_buffer, byteswritten); |
---|
607 | | bytes2write -= byteswritten; |
---|
608 | | } |
---|
609 | | |
---|
610 | | // the bytes2write should always be event aligned |
---|
611 | | assert(bytes2write%m_event_size==0); |
---|
612 | | } |
---|
613 | | |
---|
614 | | return true; |
---|
615 | | } |
---|
| 621 | return retval; |
---|
| 622 | } |
---|
| 623 | |
---|
| 624 | bool MotuTransmitStreamProcessor::putFrames(unsigned int nbframes, int64_t ts) { |
---|
| 625 | m_PeriodStat.mark(m_data_buffer->getBufferFill()); |
---|
| 626 | |
---|
| 627 | debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "MotuTransmitStreamProcessor::putFrames(%d, %llu)\n", nbframes, ts); |
---|
| 628 | |
---|
| 629 | // transfer the data |
---|
| 630 | m_data_buffer->blockProcessWriteFrames(nbframes, ts); |
---|
| 631 | |
---|
| 632 | debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " New timestamp: %llu\n", ts); |
---|
| 633 | |
---|
| 634 | return true; |
---|
| 635 | } |
---|
| 636 | |
---|
846 | | bool MotuTransmitStreamProcessor::prepareForStop() { |
---|
847 | | |
---|
848 | | // If the stream is disabled or isn't running there's no need to |
---|
849 | | // wait since the MOTU *should* still be in a "zero data" state. |
---|
850 | | // |
---|
851 | | // If the m_streaming_active flag is 0 it indicates that the |
---|
852 | | // transmit callback hasn't been called since a closedown was |
---|
853 | | // requested when this function was last called. This effectively |
---|
854 | | // signifies that the streaming thread has been exitted due to an |
---|
855 | | // xrun in either the receive or transmit handlers. In this case |
---|
856 | | // there's no point in waiting for the closedown count to hit zero |
---|
857 | | // because it never will; the zero data will never get to the MOTU. |
---|
858 | | // It's best to allow an immediate stop and let the xrun handler |
---|
859 | | // proceed as best it can. |
---|
860 | | // |
---|
861 | | // The ability to detect the lack of streaming also prevents the |
---|
862 | | // "wait for stop" in the stream processor manager's stop() method |
---|
863 | | // from hitting its timeout which in turn seems to increase the |
---|
864 | | // probability of a successful recovery. |
---|
865 | | if (m_disabled || !isRunning() || !m_streaming_active) |
---|
866 | | return true; |
---|
867 | | |
---|
868 | | if (m_closedown_count < 0) { |
---|
869 | | // No closedown has been initiated, so start one now. Set |
---|
870 | | // the closedown count to the number of zero packets which |
---|
871 | | // will be sent to the MOTU before closing off the iso |
---|
872 | | // streams. FIXME: 128 packets (each containing 8 frames at |
---|
873 | | // 48 kHz) is the experimentally-determined figure for 48 |
---|
874 | | // kHz with a period size of 1024. It seems that at least |
---|
875 | | // one period of zero samples need to be sent to allow for |
---|
876 | | // inter-thread communication occuring on period boundaries. |
---|
877 | | // This needs to be confirmed for other rates and period |
---|
878 | | // sizes. |
---|
879 | | signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32); |
---|
880 | | m_closedown_count = m_period / n_events; |
---|
881 | | |
---|
882 | | // Set up a test to confirm that streaming is still active. |
---|
883 | | // If the streaming function hasn't been called by the next |
---|
884 | | // iteration through this function there's no point in |
---|
885 | | // continuing since it means the zero data will never get to |
---|
886 | | // the MOTU. |
---|
887 | | m_streaming_active = 0; |
---|
888 | | return false; |
---|
889 | | } |
---|
890 | | |
---|
891 | | // We are "go" for closedown once all requested zero packets |
---|
892 | | // (initiated by a previous call to this function) have been sent to |
---|
893 | | // the MOTU. |
---|
894 | | return m_closedown_count == 0; |
---|
895 | | } |
---|
896 | | |
---|
897 | | bool MotuTransmitStreamProcessor::prepareForStart() { |
---|
898 | | // Reset some critical variables required so the stream starts cleanly. This |
---|
899 | | // method is called once on every stream restart, including those during |
---|
900 | | // xrun recovery. Initialisations which should be done once should be |
---|
901 | | // placed in the init() method instead. |
---|
902 | | m_running = 0; |
---|
903 | | m_next_cycle = -1; |
---|
904 | | m_closedown_count = -1; |
---|
905 | | m_streaming_active = 0; |
---|
906 | | m_cycle_count = -1; |
---|
907 | | m_cycle_ofs = 0.0; |
---|
908 | | |
---|
909 | | // At this point we'll also disable the stream processor here. |
---|
910 | | // At this stage stream processors are always explicitly re-enabled |
---|
911 | | // after being started, so by starting in the disabled state we |
---|
912 | | // ensure that every start will be exactly the same. |
---|
913 | | disable(); |
---|
914 | | |
---|
915 | | return true; |
---|
916 | | } |
---|
917 | | |
---|
963 | | if (m_next_cycle < 0) |
---|
964 | | m_next_cycle = cycle; |
---|
965 | | if ((signed)cycle != m_next_cycle) { |
---|
966 | | debugOutput(DEBUG_LEVEL_VERBOSE, "lost rx cycles; received %d, expected %d\n", |
---|
967 | | cycle, m_next_cycle); |
---|
968 | | m_next_cycle = cycle; |
---|
969 | | have_lost_cycles = 1; |
---|
970 | | } |
---|
971 | | if (++m_next_cycle >= 8000) |
---|
972 | | m_next_cycle -= 8000; |
---|
973 | | |
---|
| 902 | |
---|
| 903 | enum raw1394_iso_disposition |
---|
| 904 | MotuReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length, |
---|
| 905 | unsigned char channel, unsigned char tag, unsigned char sy, |
---|
| 906 | unsigned int cycle, unsigned int dropped) { |
---|
| 907 | |
---|
| 908 | enum raw1394_iso_disposition retval=RAW1394_ISO_OK; |
---|
| 909 | // this is needed for the base class getLastCycle() to work. |
---|
| 910 | // this avoids a function call like StreamProcessor::updateLastCycle() |
---|
| 911 | m_last_cycle=cycle; |
---|
| 912 | |
---|
| 913 | // check our enable status |
---|
| 914 | if (!m_disabled && m_is_disabled) { |
---|
| 915 | // this means that we are trying to enable |
---|
| 916 | if (cycle == m_cycle_to_enable_at) { |
---|
| 917 | m_is_disabled=false; |
---|
| 918 | debugOutput(DEBUG_LEVEL_VERBOSE,"Enabling StreamProcessor %p at %d\n", |
---|
| 919 | this, cycle); |
---|
| 920 | |
---|
| 921 | // the previous timestamp is the one we need to start with |
---|
| 922 | // because we're going to update the buffer again this loop |
---|
| 923 | // using writeframes |
---|
| 924 | m_data_buffer->setBufferTailTimestamp(m_last_timestamp2); |
---|
| 925 | |
---|
| 926 | } else { |
---|
| 927 | debugOutput(DEBUG_LEVEL_VERY_VERBOSE, |
---|
| 928 | "will enable StreamProcessor %p at %u, now is %d\n", |
---|
| 929 | this, m_cycle_to_enable_at, cycle); |
---|
| 930 | } |
---|
| 931 | } else if (m_disabled && !m_is_disabled) { |
---|
| 932 | // trying to disable |
---|
| 933 | debugOutput(DEBUG_LEVEL_VERBOSE,"disabling StreamProcessor %p at %u\n", this, cycle); |
---|
| 934 | m_is_disabled=true; |
---|
| 935 | } |
---|
| 936 | |
---|
996 | | if (n_events) m_running=true; |
---|
997 | | |
---|
998 | | /* Send actual ticks-per-frame values (as deduced by the |
---|
999 | | * incoming SPHs) to the DLL for averaging. Doing this here |
---|
1000 | | * means the DLL should acquire a reasonable estimation of |
---|
1001 | | * the ticks per frame even while the stream is formally |
---|
1002 | | * disabled. This in turn means the transmit stream should |
---|
1003 | | * have access to a very realistic estimate by the time it |
---|
1004 | | * is enabled. The major disadvantage is a small increase |
---|
1005 | | * in the overheads of this function compared to what would |
---|
1006 | | * be the case if this was delayed by pushing it into the |
---|
1007 | | * decode functions. |
---|
1008 | | */ |
---|
1009 | | unsigned int ev; |
---|
1010 | | signed int sph_ofs; |
---|
1011 | | |
---|
1012 | | /* If this is the first block received or we have lost |
---|
1013 | | * cycles, initialise the m_last_cycle_ofs to a value which |
---|
1014 | | * won't cause the DLL to become polluted with an |
---|
1015 | | * inappropriate ticks-per-frame estimate. |
---|
1016 | | */ |
---|
1017 | | if (m_last_cycle_ofs<0 || have_lost_cycles) { |
---|
1018 | | sph_ofs = ntohl(*(quadlet_t *)(data+8)) & 0xfff; |
---|
1019 | | m_last_cycle_ofs = sph_ofs-(int)(m_ticks_per_frame); |
---|
1020 | | } |
---|
1021 | | for (ev=0; ev<n_events; ev++) { |
---|
1022 | | sph_ofs = ntohl(*(quadlet_t *)(data+8+ev*m_event_size)) & 0xfff; |
---|
1023 | | signed int sph_diff = (sph_ofs - m_last_cycle_ofs); |
---|
1024 | | // Handle wraparound of the cycle offset |
---|
1025 | | if (sph_diff < 0) |
---|
1026 | | sph_diff += 3072; |
---|
1027 | | float err = sph_diff - m_ticks_per_frame; |
---|
1028 | | // FIXME: originally we used a value of 0.0005 for |
---|
1029 | | // the coefficient which mirrored the value used in |
---|
1030 | | // AmdtpReceiveStreamProcessor::putPacket() for a |
---|
1031 | | // similar purpose. However, tests showed that this |
---|
1032 | | // introduced discontinuities in the output audio |
---|
1033 | | // signal, so an alternative value was sought. |
---|
1034 | | // Further tests are needed, but a value of 0.015 |
---|
1035 | | // seems to work well, at least at a sample rate of |
---|
1036 | | // 48 kHz. |
---|
1037 | | m_ticks_per_frame += 0.015*err; |
---|
1038 | | m_last_cycle_ofs = sph_ofs; |
---|
1039 | | } |
---|
1040 | | |
---|
1041 | | // Don't process the stream when it is not enabled |
---|
1042 | | if (m_disabled) { |
---|
1043 | | return RAW1394_ISO_OK; |
---|
1044 | | } |
---|
1045 | | |
---|
1046 | | // If closedown is active we also just throw data way, but |
---|
1047 | | // in this case we keep the frame counter going to prevent a |
---|
1048 | | // false xrun detection |
---|
1049 | | if (m_closedown_active) { |
---|
1050 | | incrementFrameCounter(n_events); |
---|
1051 | | if (m_framecounter > (signed int)m_period) |
---|
1052 | | return RAW1394_ISO_DEFER; |
---|
1053 | | return RAW1394_ISO_OK; |
---|
1054 | | } |
---|
| 968 | if(!m_running && n_events && m_last_timestamp2 && m_last_timestamp) { |
---|
| 969 | debugOutput(DEBUG_LEVEL_VERBOSE,"Receive StreamProcessor %p started running at %d\n", this, cycle); |
---|
| 970 | m_running=true; |
---|
| 971 | } |
---|
| 972 | |
---|
| 973 | //=> don't process the stream samples when it is not enabled. |
---|
| 974 | if(m_is_disabled) { |
---|
| 975 | |
---|
| 976 | // we keep track of the timestamp here |
---|
| 977 | // this makes sure that we will have a somewhat accurate |
---|
| 978 | // estimate as to when a period might be ready. i.e. it will not |
---|
| 979 | // be ready earlier than this timestamp + period time |
---|
| 980 | |
---|
| 981 | // the next (possible) sample is not this one, but lies |
---|
| 982 | // SYT_INTERVAL * rate later |
---|
| 983 | float frame_size=m_framerate<=48000?8:(m_framerate<=96000?16:32); |
---|
| 984 | uint64_t ts=addTicks(m_last_timestamp, |
---|
| 985 | (uint64_t)(frame_size * m_ticks_per_frame)); |
---|
| 986 | |
---|
| 987 | // set the timestamp as if there will be a sample put into |
---|
| 988 | // the buffer by the next packet. |
---|
| 989 | m_data_buffer->setBufferTailTimestamp(ts); |
---|
| 990 | |
---|
| 991 | return RAW1394_ISO_DEFER; |
---|
| 992 | } |
---|
1058 | | // Add the data payload (events) to the ringbuffer. We'll |
---|
1059 | | // just copy everything including the 4 byte timestamp at |
---|
1060 | | // the start of each event (that is, everything except the |
---|
1061 | | // CIP-like header). The demultiplexer can deal with the |
---|
1062 | | // complexities such as the channel 24-bit data. |
---|
1063 | | unsigned int write_size = length-8; |
---|
1064 | | if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size) { |
---|
1065 | | debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n", |
---|
1066 | | cycle, m_framecounter, m_handler->getPacketCount()); |
---|
1067 | | m_xruns++; |
---|
1068 | | |
---|
1069 | | retval=RAW1394_ISO_DEFER; |
---|
1070 | | } else { |
---|
1071 | | retval=RAW1394_ISO_OK; |
---|
1072 | | // Process all ports that should be handled on a |
---|
1073 | | // per-packet basis. This is MIDI for AMDTP (due to |
---|
1074 | | // the need of DBC) |
---|
1075 | | int dbc = get_bits(ntohl(quadlet[0]), 8, 8); // Low byte of CIP quadlet 0 |
---|
1076 | | if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) { |
---|
1077 | | debugWarning("Problem decoding Packet Ports\n"); |
---|
1078 | | retval=RAW1394_ISO_DEFER; |
---|
1079 | | } |
---|
1080 | | // time stamp processing can be done here |
---|
1081 | | } |
---|
1082 | | |
---|
1083 | | // update the frame counter |
---|
1084 | | incrementFrameCounter(n_events); |
---|
1085 | | // keep this at the end, because otherwise the |
---|
1086 | | // raw1394_loop_iterate functions inner loop keeps |
---|
1087 | | // requesting packets without going to the xmit handler, |
---|
1088 | | // leading to xmit starvation |
---|
1089 | | if(m_framecounter>(signed int)m_period) { |
---|
1090 | | retval=RAW1394_ISO_DEFER; |
---|
1091 | | } |
---|
1092 | | |
---|
1093 | | } else { // no events in packet |
---|
1094 | | // discard packet |
---|
1095 | | // can be important for sync though |
---|
1096 | | } |
---|
1097 | | |
---|
| 996 | //=> process the packet |
---|
| 997 | // add the data payload to the ringbuffer |
---|
| 998 | if(m_data_buffer->writeFrames(n_events, (char *)(data+8), m_last_timestamp)) { |
---|
| 999 | retval=RAW1394_ISO_OK; |
---|
| 1000 | |
---|
| 1001 | int dbc = get_bits(ntohl(quadlet[0]), 8, 8); |
---|
| 1002 | |
---|
| 1003 | // process all ports that should be handled on a per-packet base |
---|
| 1004 | // this is MIDI for AMDTP (due to the need of DBC) |
---|
| 1005 | if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) { |
---|
| 1006 | debugWarning("Problem decoding Packet Ports\n"); |
---|
| 1007 | retval=RAW1394_ISO_DEFER; |
---|
| 1008 | } |
---|
| 1009 | |
---|
| 1010 | } else { |
---|
| 1011 | |
---|
| 1012 | debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n", |
---|
| 1013 | cycle, m_data_buffer->getFrameCounter(), m_handler->getPacketCount()); |
---|
| 1014 | |
---|
| 1015 | m_xruns++; |
---|
| 1016 | |
---|
| 1017 | // disable the processing, will be re-enabled when |
---|
| 1018 | // the xrun is handled |
---|
| 1019 | m_disabled=true; |
---|
| 1020 | m_is_disabled=true; |
---|
| 1021 | |
---|
| 1022 | retval=RAW1394_ISO_DEFER; |
---|
| 1023 | } |
---|
| 1024 | } |
---|
| 1025 | |
---|
1243 | | bool MotuReceiveStreamProcessor::transfer() { |
---|
1244 | | |
---|
1245 | | // the same idea as the transmit processor |
---|
1246 | | |
---|
1247 | | debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); |
---|
1248 | | |
---|
1249 | | /* another naive section: |
---|
1250 | | unsigned int read_size=m_period*m_event_size; |
---|
1251 | | char *dummybuffer=(char *)calloc(m_period,m_event_size); |
---|
1252 | | if (freebob_ringbuffer_read(m_event_buffer,(char *)(dummybuffer),read_size) < read_size) { |
---|
1253 | | debugWarning("Could not read from event buffer\n"); |
---|
1254 | | } |
---|
1255 | | |
---|
1256 | | receiveBlock(dummybuffer, m_period, 0); |
---|
1257 | | |
---|
1258 | | free(dummybuffer); |
---|
1259 | | */ |
---|
1260 | | int xrun; |
---|
1261 | | unsigned int offset=0; |
---|
1262 | | |
---|
1263 | | freebob_ringbuffer_data_t vec[2]; |
---|
1264 | | // We received one period of frames from each channel. |
---|
1265 | | // This is period_size*m_event_size bytes. |
---|
1266 | | unsigned int bytes2read = m_period * m_event_size; |
---|
1267 | | |
---|
1268 | | // If closedown is in progress just pretend that data's been transferred |
---|
1269 | | // to prevent false underrun detections on the event buffer. |
---|
1270 | | if (m_closedown_active) |
---|
1271 | | return true; |
---|
1272 | | |
---|
1273 | | /* Read events2read bytes from the ringbuffer. |
---|
1274 | | * First see if it can be done in one read. If so, ok. |
---|
1275 | | * Otherwise read up to a multiple of events directly from the buffer |
---|
1276 | | * then do the buffer wrap around using ringbuffer_read |
---|
1277 | | * then read the remaining data directly from the buffer in a third pass |
---|
1278 | | * Make sure that we cannot end up on a non-event aligned position! |
---|
1279 | | */ |
---|
1280 | | while(bytes2read>0) { |
---|
1281 | | unsigned int framesread=(m_period*m_event_size-bytes2read)/m_event_size; |
---|
1282 | | offset=framesread; |
---|
1283 | | |
---|
1284 | | int bytesread=0; |
---|
1285 | | |
---|
1286 | | freebob_ringbuffer_get_read_vector(m_event_buffer, vec); |
---|
1287 | | |
---|
1288 | | if(vec[0].len==0) { // this indicates an empty event buffer |
---|
1289 | | debugError("RCV: Event buffer underrun in processor %p\n",this); |
---|
1290 | | break; |
---|
1291 | | } |
---|
1292 | | |
---|
1293 | | /* if we don't take care we will get stuck in an infinite loop |
---|
1294 | | * because we align to an event boundary later |
---|
1295 | | * the remaining nb of bytes in one read operation can be smaller than one event |
---|
1296 | | * this can happen because the ringbuffer size is always a power of 2 |
---|
1297 | | */ |
---|
1298 | | if(vec[0].len<m_event_size) { |
---|
1299 | | // use the ringbuffer function to read one event |
---|
1300 | | // the read function handles wrap around |
---|
1301 | | freebob_ringbuffer_read(m_event_buffer,m_tmp_event_buffer,m_event_size); |
---|
1302 | | |
---|
1303 | | xrun = receiveBlock(m_tmp_event_buffer, 1, offset); |
---|
1304 | | |
---|
1305 | | if(xrun<0) { |
---|
1306 | | // xrun detected |
---|
1307 | | debugError("RCV: Frame buffer overrun in processor %p\n",this); |
---|
1308 | | break; |
---|
1309 | | } |
---|
1310 | | |
---|
1311 | | // We advanced one m_event_size |
---|
1312 | | bytes2read-=m_event_size; |
---|
1313 | | |
---|
1314 | | } else { // |
---|
1315 | | |
---|
1316 | | if(bytes2read>vec[0].len) { |
---|
1317 | | // align to an event boundary |
---|
1318 | | bytesread=vec[0].len-(vec[0].len%m_event_size); |
---|
1319 | | } else { |
---|
1320 | | bytesread=bytes2read; |
---|
1321 | | } |
---|
1322 | | |
---|
1323 | | xrun = receiveBlock(vec[0].buf, bytesread/m_event_size, offset); |
---|
1324 | | |
---|
1325 | | if(xrun<0) { |
---|
1326 | | // xrun detected |
---|
1327 | | debugError("RCV: Frame buffer overrun in processor %p\n",this); |
---|
1328 | | break; |
---|
1329 | | } |
---|
1330 | | |
---|
1331 | | freebob_ringbuffer_read_advance(m_event_buffer, bytesread); |
---|
1332 | | bytes2read -= bytesread; |
---|
1333 | | } |
---|
1334 | | |
---|
1335 | | // the bytes2read should always be event aligned |
---|
1336 | | assert(bytes2read%m_event_size==0); |
---|
1337 | | } |
---|
1338 | | |
---|
| 1168 | |
---|
| 1169 | bool MotuReceiveStreamProcessor::prepareForStop() { |
---|
| 1170 | |
---|
| 1171 | // A MOTU receive stream can stop at any time. However, signify |
---|
| 1172 | // that stopping is in progress because other streams (notably the |
---|
| 1173 | // transmit stream) may keep going for some time and cause an |
---|
| 1174 | // overflow in the receive buffers. If a closedown is in progress |
---|
| 1175 | // the receive handler simply throws all incoming data away so |
---|
| 1176 | // no buffer overflow can occur. |
---|
| 1177 | m_closedown_active = 1; |
---|
1526 | | bool MotuReceiveStreamProcessor::prepareForStop() { |
---|
1527 | | |
---|
1528 | | // A MOTU receive stream can stop at any time. However, signify |
---|
1529 | | // that stopping is in progress because other streams (notably the |
---|
1530 | | // transmit stream) may keep going for some time and cause an |
---|
1531 | | // overflow in the receive buffers. If a closedown is in progress |
---|
1532 | | // the receive handler simply throws all incoming data away so |
---|
1533 | | // no buffer overflow can occur. |
---|
1534 | | m_closedown_active = 1; |
---|
1535 | | return true; |
---|
1536 | | } |
---|
1537 | | |
---|
1538 | | bool MotuReceiveStreamProcessor::prepareForStart() { |
---|
1539 | | // Reset some critical variables required so the stream starts cleanly. This |
---|
1540 | | // method is called once on every stream restart, including those during |
---|
1541 | | // xrun recovery. Initialisations which should be done once should be |
---|
1542 | | // placed in the init() method instead. |
---|
1543 | | m_running = 0; |
---|
1544 | | m_next_cycle = -1; |
---|
1545 | | m_closedown_active = 0; |
---|
1546 | | m_last_cycle_ofs = -1; |
---|
1547 | | |
---|
1548 | | // At this point we'll also disable the stream processor here. |
---|
1549 | | // At this stage stream processors are always explicitly re-enabled |
---|
1550 | | // after being started, so by starting in the disabled state we |
---|
1551 | | // ensure that every start will be exactly the same. |
---|
1552 | | disable(); |
---|
1553 | | |
---|
1554 | | return true; |
---|
1555 | | } |
---|
1556 | | |
---|
1557 | | |
---|
| 1394 | void MotuReceiveStreamProcessor::setVerboseLevel(int l) { |
---|
| 1395 | setDebugLevel(l); |
---|
| 1396 | ReceiveStreamProcessor::setVerboseLevel(l); |
---|
| 1397 | } |
---|
| 1398 | |
---|