275 | | bool StreamProcessorManager::syncStartAll() { |
---|
276 | | |
---|
277 | | debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for StreamProcessor streams to start running...\n"); |
---|
278 | | // we have to wait until all streamprocessors indicate that they are running |
---|
279 | | // i.e. that there is actually some data stream flowing |
---|
280 | | int wait_cycles=RUNNING_TIMEOUT_MSEC; // two seconds |
---|
281 | | bool notRunning=true; |
---|
282 | | while (notRunning && wait_cycles) { |
---|
283 | | wait_cycles--; |
---|
284 | | notRunning=false; |
---|
285 | | |
---|
| 246 | bool StreamProcessorManager::startDryRunning() { |
---|
| 247 | debugOutput( DEBUG_LEVEL_VERBOSE, "Putting StreamProcessor streams into dry-running state...\n"); |
---|
| 248 | debugOutput( DEBUG_LEVEL_VERBOSE, " Schedule start dry-running...\n"); |
---|
| 249 | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
| 250 | it != m_ReceiveProcessors.end(); |
---|
| 251 | ++it ) { |
---|
| 252 | if (!(*it)->isDryRunning()) { |
---|
| 253 | if(!(*it)->scheduleStartDryRunning(-1)) { |
---|
| 254 | debugError("Could not put SP %p into the dry-running state\n", *it); |
---|
| 255 | return false; |
---|
| 256 | } |
---|
| 257 | } else { |
---|
| 258 | debugOutput( DEBUG_LEVEL_VERBOSE, " SP %p already dry-running...\n", *it); |
---|
| 259 | } |
---|
| 260 | } |
---|
| 261 | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
| 262 | it != m_TransmitProcessors.end(); |
---|
| 263 | ++it ) { |
---|
| 264 | if (!(*it)->isDryRunning()) { |
---|
| 265 | if(!(*it)->scheduleStartDryRunning(-1)) { |
---|
| 266 | debugError("Could not put SP %p into the dry-running state\n", *it); |
---|
| 267 | return false; |
---|
| 268 | } |
---|
| 269 | } else { |
---|
| 270 | debugOutput( DEBUG_LEVEL_VERBOSE, " SP %p already dry-running...\n", *it); |
---|
| 271 | } |
---|
| 272 | } |
---|
| 273 | debugOutput( DEBUG_LEVEL_VERBOSE, " Waiting for all SP's to be dry-running...\n"); |
---|
| 274 | // wait for the syncsource to start running. |
---|
| 275 | // that will block the waitForPeriod call until everyone has started (theoretically) |
---|
| 276 | #define CYCLES_FOR_DRYRUN 40000 |
---|
| 277 | int cnt = CYCLES_FOR_DRYRUN; // by then it should have started |
---|
| 278 | bool all_dry_running = false; |
---|
| 279 | while (!all_dry_running && cnt) { |
---|
| 280 | all_dry_running = true; |
---|
333 | | if(!(*it)->isRunning()) { |
---|
334 | | debugFatal(" transmit stream %p not running\n",*it); |
---|
335 | | } else { |
---|
336 | | debugFatal(" transmit stream %p running\n",*it); |
---|
337 | | } |
---|
338 | | } |
---|
339 | | return false; |
---|
340 | | } |
---|
341 | | |
---|
342 | | // we want to make sure that everything is running well, |
---|
343 | | // so wait for a while |
---|
344 | | usleep(USECS_PER_CYCLE * CYCLES_TO_SLEEP_AFTER_RUN_SIGNAL); |
---|
345 | | |
---|
| 306 | debugOutput( DEBUG_LEVEL_VERBOSE, " %s SP %p has state %s\n", |
---|
| 307 | (*it)->getTypeString(), *it, (*it)->getStateString()); |
---|
| 308 | } |
---|
| 309 | return false; |
---|
| 310 | } |
---|
| 311 | debugOutput( DEBUG_LEVEL_VERBOSE, " StreamProcessor streams dry-running...\n"); |
---|
| 312 | return true; |
---|
| 313 | } |
---|
| 314 | |
---|
| 315 | bool StreamProcessorManager::syncStartAll() { |
---|
| 316 | // figure out when to get the SP's running. |
---|
| 317 | // the xmit SP's should also know the base timestamp |
---|
| 318 | // streams should be aligned here |
---|
| 319 | |
---|
| 320 | // now find out how long we have to delay the wait operation such that |
---|
| 321 | // the received frames will all be presented to the SP |
---|
| 322 | debugOutput( DEBUG_LEVEL_VERBOSE, "Finding minimal sync delay...\n"); |
---|
| 323 | int max_of_min_delay = 0; |
---|
| 324 | int min_delay = 0; |
---|
| 325 | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
| 326 | it != m_ReceiveProcessors.end(); |
---|
| 327 | ++it ) { |
---|
| 328 | min_delay = (*it)->getMaxFrameLatency(); |
---|
| 329 | if(min_delay > max_of_min_delay) max_of_min_delay = min_delay; |
---|
| 330 | } |
---|
| 331 | |
---|
| 332 | // add some processing margin. This only shifts the time |
---|
| 333 | // at which the buffer is transfer()'ed. This makes things somewhat |
---|
| 334 | // more robust. It should be noted though that shifting the transfer |
---|
| 335 | // time to a later time instant also causes the xmit buffer fill to be |
---|
| 336 | // lower on average. |
---|
| 337 | max_of_min_delay += FFADO_SIGNAL_DELAY_TICKS; |
---|
| 338 | debugOutput( DEBUG_LEVEL_VERBOSE, " sync delay = %d ticks (%03us %04uc %04ut)...\n", |
---|
| 339 | max_of_min_delay, |
---|
| 340 | (unsigned int)TICKS_TO_SECS(max_of_min_delay), |
---|
| 341 | (unsigned int)TICKS_TO_CYCLES(max_of_min_delay), |
---|
| 342 | (unsigned int)TICKS_TO_OFFSET(max_of_min_delay)); |
---|
| 343 | m_SyncSource->setSyncDelay(max_of_min_delay); |
---|
| 344 | |
---|
| 345 | //STEP X: when we implement such a function, we can wait for a signal from the devices that they |
---|
| 346 | // have aquired lock |
---|
| 347 | //debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for device(s) to indicate clock sync lock...\n"); |
---|
| 348 | //sleep(2); // FIXME: be smarter here |
---|
| 349 | |
---|
| 350 | // make sure that we are dry-running long enough for the |
---|
| 351 | // DLL to have a decent sync (FIXME: does the DLL get updated when dry-running)? |
---|
| 352 | debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for sync...\n"); |
---|
| 353 | int nb_sync_runs=20; |
---|
| 354 | int64_t time_till_next_period; |
---|
| 355 | while(nb_sync_runs--) { // or while not sync-ed? |
---|
| 356 | // check if we were woken up too soon |
---|
| 357 | time_till_next_period = m_SyncSource->getTimeUntilNextPeriodSignalUsecs(); |
---|
| 358 | debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "waiting for %d usecs...\n", time_till_next_period); |
---|
| 359 | if(time_till_next_period > 0) { |
---|
| 360 | // wait for the period |
---|
| 361 | usleep(time_till_next_period); |
---|
| 362 | } |
---|
| 363 | } |
---|
| 364 | |
---|
| 365 | debugOutput( DEBUG_LEVEL_VERBOSE, "Propagate sync info...\n"); |
---|
| 366 | // FIXME: in the SPM it would be nice to have system time instead of |
---|
| 367 | // 1394 time |
---|
| 368 | |
---|
| 369 | // we now should have decent sync info on the sync source |
---|
| 370 | // determine a point in time where the system should start |
---|
| 371 | // figure out where we are now |
---|
| 372 | uint64_t time_of_first_sample = m_SyncSource->getTimeAtPeriod(); |
---|
| 373 | debugOutput( DEBUG_LEVEL_VERBOSE, " sync at TS=%011llu (%03us %04uc %04ut)...\n", |
---|
| 374 | time_of_first_sample, |
---|
| 375 | (unsigned int)TICKS_TO_SECS(time_of_first_sample), |
---|
| 376 | (unsigned int)TICKS_TO_CYCLES(time_of_first_sample), |
---|
| 377 | (unsigned int)TICKS_TO_OFFSET(time_of_first_sample)); |
---|
| 378 | |
---|
| 379 | #define CYCLES_FOR_STARTUP 2000 |
---|
| 380 | // start wet-running in CYCLES_FOR_STARTUP cycles |
---|
| 381 | // this is the time window we have to setup all SP's such that they |
---|
| 382 | // can start wet-running correctly. |
---|
| 383 | time_of_first_sample = addTicks(time_of_first_sample, |
---|
| 384 | CYCLES_FOR_STARTUP * TICKS_PER_CYCLE); |
---|
| 385 | |
---|
| 386 | debugOutput( DEBUG_LEVEL_VERBOSE, " => first sample at TS=%011llu (%03us %04uc %04ut)...\n", |
---|
| 387 | time_of_first_sample, |
---|
| 388 | (unsigned int)TICKS_TO_SECS(time_of_first_sample), |
---|
| 389 | (unsigned int)TICKS_TO_CYCLES(time_of_first_sample), |
---|
| 390 | (unsigned int)TICKS_TO_OFFSET(time_of_first_sample)); |
---|
| 391 | |
---|
| 392 | // we should start wet-running the transmit SP's some cycles in advance |
---|
| 393 | // such that we know it is wet-running when it should output its first sample |
---|
| 394 | #define PRESTART_CYCLES_FOR_XMIT 20 |
---|
| 395 | uint64_t time_to_start_xmit = substractTicks(time_of_first_sample, |
---|
| 396 | PRESTART_CYCLES_FOR_XMIT * TICKS_PER_CYCLE); |
---|
| 397 | |
---|
| 398 | #define PRESTART_CYCLES_FOR_RECV 0 |
---|
| 399 | uint64_t time_to_start_recv = substractTicks(time_of_first_sample, |
---|
| 400 | PRESTART_CYCLES_FOR_RECV * TICKS_PER_CYCLE); |
---|
| 401 | debugOutput( DEBUG_LEVEL_VERBOSE, " => xmit starts at TS=%011llu (%03us %04uc %04ut)...\n", |
---|
| 402 | time_to_start_xmit, |
---|
| 403 | (unsigned int)TICKS_TO_SECS(time_to_start_xmit), |
---|
| 404 | (unsigned int)TICKS_TO_CYCLES(time_to_start_xmit), |
---|
| 405 | (unsigned int)TICKS_TO_OFFSET(time_to_start_xmit)); |
---|
| 406 | debugOutput( DEBUG_LEVEL_VERBOSE, " => recv starts at TS=%011llu (%03us %04uc %04ut)...\n", |
---|
| 407 | time_to_start_recv, |
---|
| 408 | (unsigned int)TICKS_TO_SECS(time_to_start_recv), |
---|
| 409 | (unsigned int)TICKS_TO_CYCLES(time_to_start_recv), |
---|
| 410 | (unsigned int)TICKS_TO_OFFSET(time_to_start_recv)); |
---|
| 411 | |
---|
| 412 | // at this point the buffer head timestamp of the transmit buffers can be set |
---|
| 413 | // this is the presentation time of the first sample in the buffer |
---|
| 414 | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
| 415 | it != m_TransmitProcessors.end(); |
---|
| 416 | ++it ) { |
---|
| 417 | (*it)->setBufferHeadTimestamp(time_of_first_sample); |
---|
| 418 | } |
---|
| 419 | |
---|
| 420 | // STEP X: switch SP's over to the running state |
---|
| 421 | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
| 422 | it != m_ReceiveProcessors.end(); |
---|
| 423 | ++it ) { |
---|
| 424 | if(!(*it)->scheduleStartRunning(time_to_start_recv)) { |
---|
| 425 | debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_recv); |
---|
| 426 | return false; |
---|
| 427 | } |
---|
| 428 | } |
---|
| 429 | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
| 430 | it != m_TransmitProcessors.end(); |
---|
| 431 | ++it ) { |
---|
| 432 | if(!(*it)->scheduleStartRunning(time_to_start_xmit)) { |
---|
| 433 | debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_xmit); |
---|
| 434 | return false; |
---|
| 435 | } |
---|
| 436 | } |
---|
| 437 | // wait for the syncsource to start running. |
---|
| 438 | // that will block the waitForPeriod call until everyone has started (theoretically) |
---|
| 439 | int cnt = CYCLES_FOR_STARTUP * 2; // by then it should have started |
---|
| 440 | while (!m_SyncSource->isRunning() && cnt) { |
---|
| 441 | usleep(125); |
---|
| 442 | cnt--; |
---|
| 443 | } |
---|
| 444 | if(cnt==0) { |
---|
| 445 | debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout waiting for the SyncSource to get started\n"); |
---|
| 446 | return false; |
---|
| 447 | } |
---|
| 448 | |
---|
| 449 | // now align the received streams |
---|
| 450 | if(!alignReceivedStreams()) { |
---|
| 451 | debugError("Could not align streams\n"); |
---|
| 452 | return false; |
---|
| 453 | } |
---|
347 | | |
---|
348 | | debugOutput( DEBUG_LEVEL_VERBOSE, "Finding minimal sync delay...\n"); |
---|
349 | | |
---|
350 | | int max_of_min_delay=0; |
---|
351 | | int min_delay=0; |
---|
352 | | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
353 | | it != m_ReceiveProcessors.end(); |
---|
354 | | ++it ) { |
---|
355 | | min_delay=(*it)->getMinimalSyncDelay(); |
---|
356 | | if(min_delay>max_of_min_delay) max_of_min_delay=min_delay; |
---|
357 | | } |
---|
358 | | |
---|
359 | | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
360 | | it != m_TransmitProcessors.end(); |
---|
361 | | ++it ) { |
---|
362 | | min_delay=(*it)->getMinimalSyncDelay(); |
---|
363 | | if(min_delay>max_of_min_delay) max_of_min_delay=min_delay; |
---|
364 | | } |
---|
365 | | |
---|
366 | | debugOutput( DEBUG_LEVEL_VERBOSE, " %d ticks\n", max_of_min_delay); |
---|
367 | | m_SyncSource->setSyncDelay(max_of_min_delay); |
---|
368 | | |
---|
369 | | |
---|
370 | | debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting StreamProcessors...\n"); |
---|
371 | | // now we reset the frame counters |
---|
372 | | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
373 | | it != m_ReceiveProcessors.end(); |
---|
374 | | ++it ) { |
---|
375 | | (*it)->reset(); |
---|
376 | | } |
---|
377 | | |
---|
378 | | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
379 | | it != m_TransmitProcessors.end(); |
---|
380 | | ++it ) { |
---|
381 | | (*it)->reset(); |
---|
382 | | } |
---|
383 | | |
---|
384 | | debugOutput( DEBUG_LEVEL_VERBOSE, "Enabling StreamProcessors...\n"); |
---|
385 | | |
---|
386 | | uint64_t now=m_SyncSource->getTimeNow(); // fixme: should be in usecs, not ticks |
---|
387 | | |
---|
388 | | // FIXME: this should not be in cycles, but in 'time' |
---|
389 | | unsigned int enable_at=TICKS_TO_CYCLES(now)+ENABLE_DELAY_CYCLES; |
---|
390 | | if (enable_at > 8000) enable_at -= 8000; |
---|
391 | | |
---|
392 | | if (!enableStreamProcessors(enable_at)) { |
---|
393 | | debugFatal("Could not enable StreamProcessors...\n"); |
---|
394 | | return false; |
---|
395 | | } |
---|
396 | | |
---|
| 455 | return true; |
---|
| 456 | } |
---|
| 457 | |
---|
| 458 | bool |
---|
| 459 | StreamProcessorManager::alignReceivedStreams() |
---|
| 460 | { |
---|
| 461 | #define NB_PERIODS_FOR_ALIGN_AVERAGE 20 |
---|
| 462 | #define NB_ALIGN_TRIES 20 |
---|
| 463 | debugOutput( DEBUG_LEVEL_VERBOSE, "Aligning received streams...\n"); |
---|
| 464 | unsigned int nb_sync_runs; |
---|
| 465 | unsigned int nb_rcv_sp = m_ReceiveProcessors.size(); |
---|
| 466 | int64_t diff_between_streams[nb_rcv_sp]; |
---|
| 467 | int64_t diff; |
---|
| 468 | |
---|
| 469 | unsigned int i; |
---|
| 470 | |
---|
| 471 | bool aligned = false; |
---|
| 472 | int cnt = NB_ALIGN_TRIES; |
---|
| 473 | while (!aligned && cnt--) { |
---|
| 474 | nb_sync_runs = NB_PERIODS_FOR_ALIGN_AVERAGE; |
---|
| 475 | while(nb_sync_runs) { |
---|
| 476 | debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " check (%d)...\n", nb_sync_runs); |
---|
| 477 | waitForPeriod(); |
---|
| 478 | |
---|
| 479 | i = 0; |
---|
| 480 | for ( i = 0; i < nb_rcv_sp; i++) { |
---|
| 481 | StreamProcessor *s = m_ReceiveProcessors.at(i); |
---|
| 482 | diff = diffTicks(m_SyncSource->getTimeAtPeriod(), s->getTimeAtPeriod()); |
---|
| 483 | debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " offset between SyncSP %p and SP %p is %lld ticks...\n", |
---|
| 484 | m_SyncSource, s, diff); |
---|
| 485 | if ( nb_sync_runs == NB_PERIODS_FOR_ALIGN_AVERAGE ) { |
---|
| 486 | diff_between_streams[i] = diff; |
---|
| 487 | } else { |
---|
| 488 | diff_between_streams[i] += diff; |
---|
| 489 | } |
---|
| 490 | } |
---|
| 491 | if(!transferSilence()) { |
---|
| 492 | debugError("Could not transfer silence\n"); |
---|
| 493 | return false; |
---|
| 494 | } |
---|
| 495 | nb_sync_runs--; |
---|
| 496 | } |
---|
| 497 | // calculate the average offsets |
---|
| 498 | debugOutput( DEBUG_LEVEL_VERBOSE, " Average offsets:\n"); |
---|
| 499 | int diff_between_streams_frames[nb_rcv_sp]; |
---|
| 500 | aligned = true; |
---|
| 501 | for ( i = 0; i < nb_rcv_sp; i++) { |
---|
| 502 | StreamProcessor *s = m_ReceiveProcessors.at(i); |
---|
| 503 | |
---|
| 504 | diff_between_streams[i] /= NB_PERIODS_FOR_ALIGN_AVERAGE; |
---|
| 505 | diff_between_streams_frames[i] = roundf(diff_between_streams[i] / s->getTicksPerFrame()); |
---|
| 506 | debugOutput( DEBUG_LEVEL_VERBOSE, " avg offset between SyncSP %p and SP %p is %lld ticks, %d frames...\n", |
---|
| 507 | m_SyncSource, s, diff_between_streams[i], diff_between_streams_frames[i]); |
---|
| 508 | |
---|
| 509 | aligned &= (diff_between_streams_frames[i] == 0); |
---|
| 510 | |
---|
| 511 | // reposition the stream |
---|
| 512 | if(!s->shiftStream(diff_between_streams_frames[i])) { |
---|
| 513 | debugError("Could not shift SP %p %d frames\n", s, diff_between_streams_frames[i]); |
---|
| 514 | return false; |
---|
| 515 | } |
---|
| 516 | } |
---|
| 517 | if (!aligned) { |
---|
| 518 | debugOutput(DEBUG_LEVEL_VERBOSE, "Streams not aligned, doing new round...\n"); |
---|
| 519 | } |
---|
| 520 | } |
---|
| 521 | if (cnt == 0) { |
---|
| 522 | debugError("Align failed\n"); |
---|
| 523 | return false; |
---|
| 524 | } |
---|
516 | | it != m_TransmitProcessors.end(); |
---|
517 | | ++it ) { |
---|
518 | | if (!m_isoManager->unregisterStream(*it)) { |
---|
519 | | debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister transmit stream processor (%p) from the Iso manager\n",*it); |
---|
520 | | return false; |
---|
521 | | } |
---|
522 | | |
---|
523 | | } |
---|
524 | | |
---|
525 | | return true; |
---|
526 | | |
---|
527 | | } |
---|
528 | | |
---|
529 | | /** |
---|
530 | | * Enables the registered StreamProcessors |
---|
531 | | * @return true if successful, false otherwise |
---|
532 | | */ |
---|
533 | | bool StreamProcessorManager::enableStreamProcessors(uint64_t time_to_enable_at) { |
---|
534 | | debugOutput( DEBUG_LEVEL_VERBOSE, "Enabling StreamProcessors at %llu...\n", time_to_enable_at); |
---|
535 | | |
---|
536 | | debugOutput( DEBUG_LEVEL_VERBOSE, " Sync Source StreamProcessor (%p)...\n",m_SyncSource); |
---|
537 | | debugOutput( DEBUG_LEVEL_VERBOSE, " Prepare...\n"); |
---|
538 | | if (!m_SyncSource->prepareForEnable(time_to_enable_at)) { |
---|
539 | | debugFatal("Could not prepare Sync Source StreamProcessor for enable()...\n"); |
---|
540 | | return false; |
---|
541 | | } |
---|
542 | | |
---|
543 | | debugOutput( DEBUG_LEVEL_VERBOSE, " Enable...\n"); |
---|
544 | | m_SyncSource->enable(time_to_enable_at); |
---|
545 | | |
---|
546 | | debugOutput( DEBUG_LEVEL_VERBOSE, " Other StreamProcessors...\n"); |
---|
547 | | |
---|
548 | | // we prepare the streamprocessors for enable |
---|
549 | | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
550 | | it != m_ReceiveProcessors.end(); |
---|
551 | | ++it ) { |
---|
552 | | if(*it != m_SyncSource) { |
---|
553 | | debugOutput( DEBUG_LEVEL_VERBOSE, " Prepare Receive SP (%p)...\n",*it); |
---|
554 | | (*it)->prepareForEnable(time_to_enable_at); |
---|
555 | | } |
---|
556 | | } |
---|
557 | | |
---|
558 | | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
559 | | it != m_TransmitProcessors.end(); |
---|
560 | | ++it ) { |
---|
561 | | if(*it != m_SyncSource) { |
---|
562 | | debugOutput( DEBUG_LEVEL_VERBOSE, " Prepare Transmit SP (%p)...\n",*it); |
---|
563 | | (*it)->prepareForEnable(time_to_enable_at); |
---|
564 | | } |
---|
565 | | } |
---|
566 | | |
---|
567 | | // then we enable the streamprocessors |
---|
568 | | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
569 | | it != m_ReceiveProcessors.end(); |
---|
570 | | ++it ) { |
---|
571 | | if(*it != m_SyncSource) { |
---|
572 | | debugOutput( DEBUG_LEVEL_VERBOSE, " Enable Receive SP (%p)...\n",*it); |
---|
573 | | (*it)->enable(time_to_enable_at); |
---|
574 | | } |
---|
575 | | } |
---|
576 | | |
---|
577 | | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
578 | | it != m_TransmitProcessors.end(); |
---|
579 | | ++it ) { |
---|
580 | | if(*it != m_SyncSource) { |
---|
581 | | debugOutput( DEBUG_LEVEL_VERBOSE, " Enable Transmit SP (%p)...\n",*it); |
---|
582 | | (*it)->enable(time_to_enable_at); |
---|
583 | | } |
---|
584 | | } |
---|
585 | | |
---|
586 | | // 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 running |
---|
589 | | // i.e. that there is actually some data stream flowing |
---|
590 | | int wait_cycles=ENABLE_TIMEOUT_MSEC; // two seconds |
---|
591 | | 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 cycle |
---|
608 | | } |
---|
609 | | |
---|
610 | | if(!wait_cycles) { // timout has occurred |
---|
611 | | 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 | | } |
---|
634 | | |
---|
635 | | debugOutput( DEBUG_LEVEL_VERBOSE, " => all StreamProcessors enabled...\n"); |
---|
636 | | |
---|
637 | | return true; |
---|
638 | | } |
---|
639 | | |
---|
640 | | /** |
---|
641 | | * Disables the registered StreamProcessors |
---|
642 | | * @return true if successful, false otherwise |
---|
643 | | */ |
---|
644 | | bool StreamProcessorManager::disableStreamProcessors() { |
---|
645 | | // we prepare the streamprocessors for disable |
---|
646 | | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
647 | | it != m_ReceiveProcessors.end(); |
---|
648 | | ++it ) { |
---|
649 | | (*it)->prepareForDisable(); |
---|
650 | | } |
---|
651 | | |
---|
652 | | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
653 | | it != m_TransmitProcessors.end(); |
---|
654 | | ++it ) { |
---|
655 | | (*it)->prepareForDisable(); |
---|
656 | | } |
---|
657 | | |
---|
658 | | // then we disable the streamprocessors |
---|
659 | | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
660 | | it != m_ReceiveProcessors.end(); |
---|
661 | | ++it ) { |
---|
662 | | (*it)->disable(); |
---|
663 | | } |
---|
664 | | |
---|
665 | | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
666 | | it != m_TransmitProcessors.end(); |
---|
667 | | ++it ) { |
---|
668 | | (*it)->disable(); |
---|
669 | | } |
---|
670 | | |
---|
671 | | // now we wait for the SP's to get disabled |
---|
672 | | debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for all StreamProcessors to be disabled...\n"); |
---|
673 | | // we have to wait until all streamprocessors indicate that they are running |
---|
674 | | // i.e. that there is actually some data stream flowing |
---|
675 | | int wait_cycles=ENABLE_TIMEOUT_MSEC; // two seconds |
---|
676 | | bool enabled=true; |
---|
677 | | while (enabled && wait_cycles) { |
---|
678 | | wait_cycles--; |
---|
679 | | enabled=false; |
---|
680 | | |
---|
681 | | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
682 | | it != m_ReceiveProcessors.end(); |
---|
683 | | ++it ) { |
---|
684 | | if((*it)->isEnabled()) enabled=true; |
---|
685 | | } |
---|
686 | | |
---|
687 | | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
688 | | it != m_TransmitProcessors.end(); |
---|
689 | | ++it ) { |
---|
690 | | if((*it)->isEnabled()) enabled=true; |
---|
691 | | } |
---|
692 | | usleep(1000); // one cycle |
---|
693 | | } |
---|
694 | | |
---|
695 | | if(!wait_cycles) { // timout has occurred |
---|
696 | | debugFatal("One or more streams couldn't be disabled (timeout):\n"); |
---|
697 | | |
---|
698 | | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
699 | | it != m_ReceiveProcessors.end(); |
---|
700 | | ++it ) { |
---|
701 | | if(!(*it)->isEnabled()) { |
---|
702 | | debugFatal(" receive stream %p not enabled\n",*it); |
---|
703 | | } else { |
---|
704 | | debugFatal(" receive stream %p enabled\n",*it); |
---|
705 | | } |
---|
706 | | } |
---|
707 | | |
---|
708 | | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
709 | | it != m_TransmitProcessors.end(); |
---|
710 | | ++it ) { |
---|
711 | | if(!(*it)->isEnabled()) { |
---|
712 | | debugFatal(" transmit stream %p not enabled\n",*it); |
---|
713 | | } else { |
---|
714 | | debugFatal(" transmit stream %p enabled\n",*it); |
---|
715 | | } |
---|
716 | | } |
---|
717 | | return false; |
---|
718 | | } |
---|
719 | | |
---|
720 | | debugOutput( DEBUG_LEVEL_VERBOSE, " => all StreamProcessors disabled...\n"); |
---|
721 | | |
---|
| 691 | it != m_TransmitProcessors.end(); |
---|
| 692 | ++it ) { |
---|
| 693 | if (!m_isoManager->unregisterStream(*it)) { |
---|
| 694 | debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister transmit stream processor (%p) from the Iso manager\n",*it); |
---|
| 695 | return false; |
---|
| 696 | } |
---|
| 697 | } |
---|
| 795 | |
---|
| 796 | // normally we can transfer frames at this time, but in some cases this is not true |
---|
| 797 | // e.g. when there are not enough frames in the receive buffer. |
---|
| 798 | // however this doesn't have to be a problem, since we can wait some more until we |
---|
| 799 | // have enough frames. There is only a problem once the ISO xmit doesn't have packets |
---|
| 800 | // to transmit, or if the receive buffer overflows. These conditions are signaled by |
---|
| 801 | // the iso threads |
---|
| 802 | // check if xruns occurred on the Iso side. |
---|
| 803 | // also check if xruns will occur should we transfer() now |
---|
| 804 | #ifdef DEBUG |
---|
| 805 | int waited = 0; |
---|
| 806 | #endif |
---|
| 807 | bool ready_for_transfer = false; |
---|
| 808 | xrun_occurred = false; |
---|
| 809 | while (!ready_for_transfer && !xrun_occurred) { |
---|
| 810 | ready_for_transfer = true; |
---|
| 811 | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
| 812 | it != m_ReceiveProcessors.end(); |
---|
| 813 | ++it ) { |
---|
| 814 | ready_for_transfer &= ((*it)->canClientTransferFrames(m_period)); |
---|
| 815 | xrun_occurred |= (*it)->xrunOccurred(); |
---|
| 816 | } |
---|
| 817 | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
| 818 | it != m_TransmitProcessors.end(); |
---|
| 819 | ++it ) { |
---|
| 820 | ready_for_transfer &= ((*it)->canClientTransferFrames(m_period)); |
---|
| 821 | xrun_occurred |= (*it)->xrunOccurred(); |
---|
| 822 | } |
---|
| 823 | if (!ready_for_transfer) { |
---|
| 824 | usleep(125); // MAGIC: one cycle sleep... |
---|
| 825 | |
---|
| 826 | // in order to avoid this in the future, we increase the sync delay of the sync source SP |
---|
| 827 | int d = m_SyncSource->getSyncDelay() + TICKS_PER_CYCLE; |
---|
| 828 | m_SyncSource->setSyncDelay(d); |
---|
| 829 | |
---|
| 830 | #ifdef DEBUG |
---|
| 831 | waited++; |
---|
| 832 | #endif |
---|
| 833 | } |
---|
| 834 | } // we are either ready or an xrun occurred |
---|
| 835 | |
---|
| 836 | #ifdef DEBUG |
---|
| 837 | if(waited > 0) { |
---|
| 838 | debugOutput(DEBUG_LEVEL_VERBOSE, "Waited %d x 125us due to SP not ready for transfer\n", waited); |
---|
| 839 | } |
---|
| 840 | #endif |
---|
| 841 | |
---|
| 842 | // this is to notify the client of the delay that we introduced by waiting |
---|
| 843 | m_delayed_usecs = - m_SyncSource->getTimeUntilNextPeriodSignalUsecs(); |
---|
| 844 | debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "delayed for %d usecs...\n", m_delayed_usecs); |
---|
953 | | |
---|
954 | | if(!(*it)->putFrames(m_period, (int64_t)m_time_of_transfer)) { |
---|
955 | | debugOutput(DEBUG_LEVEL_VERBOSE, "could not putFrames(%u,%llu) to stream processor (%p)\n", |
---|
956 | | m_period, m_time_of_transfer, *it); |
---|
957 | | return false; // buffer overrun |
---|
958 | | } |
---|
959 | | |
---|
960 | | } |
---|
961 | | } |
---|
962 | | |
---|
963 | | return true; |
---|
| 949 | // FIXME: in the SPM it would be nice to have system time instead of |
---|
| 950 | // 1394 time |
---|
| 951 | if(!(*it)->putFrames(m_period, transmit_timestamp)) { |
---|
| 952 | debugWarning("could not putFrames(%u,%llu) to stream processor (%p)\n", |
---|
| 953 | m_period, transmit_timestamp, *it); |
---|
| 954 | retval &= false; // buffer underrun |
---|
| 955 | } |
---|
| 956 | } |
---|
| 957 | } |
---|
| 958 | return retval; |
---|
| 959 | } |
---|
| 960 | |
---|
| 961 | /** |
---|
| 962 | * @brief Transfer one period of silence for both receive and transmit StreamProcessors |
---|
| 963 | * |
---|
| 964 | * Transfers one period of silence to the Iso side for transmit SP's |
---|
| 965 | * or dump one period of frames for receive SP's |
---|
| 966 | * |
---|
| 967 | * @return true if successful, false otherwise (indicates xrun). |
---|
| 968 | */ |
---|
| 969 | bool StreamProcessorManager::transferSilence() { |
---|
| 970 | debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring silent period...\n"); |
---|
| 971 | bool retval=true; |
---|
| 972 | retval &= transferSilence(StreamProcessor::ePT_Receive); |
---|
| 973 | retval &= transferSilence(StreamProcessor::ePT_Transmit); |
---|
| 974 | return retval; |
---|
| 975 | } |
---|
| 976 | |
---|
| 977 | /** |
---|
| 978 | * @brief Transfer one period of silence for either the receive or transmit StreamProcessors |
---|
| 979 | * |
---|
| 980 | * Transfers one period of silence to the Iso side for transmit SP's |
---|
| 981 | * or dump one period of frames for receive SP's |
---|
| 982 | * |
---|
| 983 | * @param t The processor type to tranfer for (receive or transmit) |
---|
| 984 | * @return true if successful, false otherwise (indicates xrun). |
---|
| 985 | */ |
---|
| 986 | bool StreamProcessorManager::transferSilence(enum StreamProcessor::eProcessorType t) { |
---|
| 987 | debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "transferSilence(%d) at TS=%011llu (%03us %04uc %04ut)...\n", |
---|
| 988 | t, m_time_of_transfer, |
---|
| 989 | (unsigned int)TICKS_TO_SECS(m_time_of_transfer), |
---|
| 990 | (unsigned int)TICKS_TO_CYCLES(m_time_of_transfer), |
---|
| 991 | (unsigned int)TICKS_TO_OFFSET(m_time_of_transfer)); |
---|
| 992 | |
---|
| 993 | bool retval = true; |
---|
| 994 | // a static cast could make sure that there is no performance |
---|
| 995 | // penalty for the virtual functions (to be checked) |
---|
| 996 | if (t==StreamProcessor::ePT_Receive) { |
---|
| 997 | for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); |
---|
| 998 | it != m_ReceiveProcessors.end(); |
---|
| 999 | ++it ) { |
---|
| 1000 | if(!(*it)->dropFrames(m_period, m_time_of_transfer)) { |
---|
| 1001 | debugWarning("could not dropFrames(%u, %11llu) from stream processor (%p)\n", |
---|
| 1002 | m_period, m_time_of_transfer,*it); |
---|
| 1003 | retval &= false; // buffer underrun |
---|
| 1004 | } |
---|
| 1005 | } |
---|
| 1006 | } else { |
---|
| 1007 | // FIXME: in the SPM it would be nice to have system time instead of |
---|
| 1008 | // 1394 time |
---|
| 1009 | float rate = m_SyncSource->getTicksPerFrame(); |
---|
| 1010 | int64_t one_ringbuffer_in_ticks=(int64_t)(((float)(m_nb_buffers * m_period)) * rate); |
---|
| 1011 | |
---|
| 1012 | // the data we are putting into the buffer is intended to be transmitted |
---|
| 1013 | // one ringbuffer size after it has been received |
---|
| 1014 | int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks); |
---|
| 1015 | |
---|
| 1016 | for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); |
---|
| 1017 | it != m_TransmitProcessors.end(); |
---|
| 1018 | ++it ) { |
---|
| 1019 | // FIXME: in the SPM it would be nice to have system time instead of |
---|
| 1020 | // 1394 time |
---|
| 1021 | if(!(*it)->putSilenceFrames(m_period, transmit_timestamp)) { |
---|
| 1022 | debugWarning("could not putSilenceFrames(%u,%llu) to stream processor (%p)\n", |
---|
| 1023 | m_period, transmit_timestamp, *it); |
---|
| 1024 | retval &= false; // buffer underrun |
---|
| 1025 | } |
---|
| 1026 | } |
---|
| 1027 | } |
---|
| 1028 | return retval; |
---|