root/branches/libffado-2.0/src/libstreaming/generic/StreamProcessor.cpp

Revision 1529, 73.6 kB (checked in by ppalmers, 15 years ago)

- don't use DEFER when we have sufficient frames. This is a huge performance killer. This might result in worse latency performance though...
- Also update the Timestampedbuffer DLL when dry-running such that we have a decent estimate of the samplerate. Use a large bandwidth for

this estimation to ensure that it tracks fast enough. Switch to a lower bandwidth once we start the actual streaming.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25
26 #include "StreamProcessor.h"
27 #include "../StreamProcessorManager.h"
28
29 #include "devicemanager.h"
30
31 #include "libieee1394/ieee1394service.h"
32 #include "libieee1394/IsoHandlerManager.h"
33 #include "libieee1394/cycletimer.h"
34
35 #include "libutil/Time.h"
36
37 #include "libutil/Atomic.h"
38
39 #include <assert.h>
40 #include <math.h>
41
42 #define SIGNAL_ACTIVITY_SPM { \
43     m_StreamProcessorManager.signalActivity(); \
44 }
45 #define SIGNAL_ACTIVITY_ISO_XMIT { \
46     m_IsoHandlerManager.signalActivityTransmit(); \
47 }
48 #define SIGNAL_ACTIVITY_ISO_RECV { \
49     m_IsoHandlerManager.signalActivityReceive(); \
50 }
51 #define SIGNAL_ACTIVITY_ALL { \
52     m_StreamProcessorManager.signalActivity(); \
53     m_IsoHandlerManager.signalActivityTransmit(); \
54     m_IsoHandlerManager.signalActivityReceive(); \
55 }
56
57 namespace Streaming {
58
59 IMPL_DEBUG_MODULE( StreamProcessor, StreamProcessor, DEBUG_LEVEL_VERBOSE );
60
61 StreamProcessor::StreamProcessor(FFADODevice &parent, enum eProcessorType type)
62     : m_processor_type ( type )
63     , m_state( ePS_Created )
64     , m_next_state( ePS_Invalid )
65     , m_cycle_to_switch_state( 0 )
66     , m_Parent( parent )
67     , m_1394service( parent.get1394Service() ) // local cache
68     , m_IsoHandlerManager( parent.get1394Service().getIsoHandlerManager() ) // local cache
69     , m_StreamProcessorManager( m_Parent.getDeviceManager().getStreamProcessorManager() ) // local cache
70     , m_local_node_id ( 0 ) // local cache
71     , m_channel( -1 )
72     , m_last_timestamp( 0 )
73     , m_last_timestamp2( 0 )
74     , m_correct_last_timestamp( false )
75     , m_scratch_buffer( NULL )
76     , m_scratch_buffer_size_bytes( 0 )
77     , m_ticks_per_frame( 0 )
78     , m_dll_bandwidth_hz ( STREAMPROCESSOR_DLL_BW_HZ )
79     , m_sync_delay( 0 )
80     , m_in_xrun( false )
81 {
82     // create the timestamped buffer and register ourselves as its client
83     m_data_buffer = new Util::TimestampedBuffer(this);
84 }
85
86 StreamProcessor::~StreamProcessor() {
87     m_StreamProcessorManager.unregisterProcessor(this);
88     if(!m_IsoHandlerManager.unregisterStream(this)) {
89         debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister stream processor with the Iso manager\n");
90     }
91
92     if (m_data_buffer) delete m_data_buffer;
93     if (m_scratch_buffer) delete[] m_scratch_buffer;
94 }
95
96 bool
97 StreamProcessor::handleBusResetDo()
98 {
99     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) handling busreset\n", this);
100     m_state = ePS_Error;
101     // this will result in the SPM dying
102     m_in_xrun = true;
103     SIGNAL_ACTIVITY_ALL;
104     return true;
105 }
106
107 bool
108 StreamProcessor::handleBusReset()
109 {
110     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) handling busreset\n", this);
111
112     // we are sure that we're not iterated since this is called from within the ISO manager thread
113
114     // lock the wait loop of the SPM, such that the client leaves us alone
115     m_StreamProcessorManager.lockWaitLoop();
116
117     // pass on to the implementing classes
118     bool retval = handleBusResetDo();
119
120     // resume wait loop
121     m_StreamProcessorManager.unlockWaitLoop();
122
123     return retval;
124 }
125
126 void StreamProcessor::handlerDied()
127 {
128     debugWarning("Handler died for %p\n", this);
129     m_state = ePS_Stopped;
130     m_in_xrun = true;
131     SIGNAL_ACTIVITY_ALL;
132 }
133
134 uint64_t StreamProcessor::getTimeNow() {
135     return m_1394service.getCycleTimerTicks();
136 }
137
138 int StreamProcessor::getMaxFrameLatency() {
139     return (int)(m_IsoHandlerManager.getPacketLatencyForStream( this ) * TICKS_PER_CYCLE);
140 }
141
142 unsigned int
143 StreamProcessor::getNominalPacketsNeeded(unsigned int nframes)
144 {
145     unsigned int nominal_frames_per_second
146                     = m_StreamProcessorManager.getNominalRate();
147     uint64_t nominal_ticks_per_frame = TICKS_PER_SECOND / nominal_frames_per_second;
148     uint64_t nominal_ticks = nominal_ticks_per_frame * nframes;
149     // ensure proper ceiling
150     uint64_t nominal_packets = (nominal_ticks+TICKS_PER_CYCLE-1) / TICKS_PER_CYCLE;
151     return nominal_packets;
152 }
153
154 unsigned int
155 StreamProcessor::getPacketsPerPeriod()
156 {
157     return getNominalPacketsNeeded(m_StreamProcessorManager.getPeriodSize());
158 }
159
160 unsigned int
161 StreamProcessor::getNbPacketsIsoXmitBuffer()
162 {
163     // if we use one thread per packet, we can put every frame directly into the ISO buffer
164     // the waitForClient in IsoHandler will take care of the fact that the frames are
165     // not present in time
166     unsigned int packets_to_prebuffer = (getPacketsPerPeriod() * (m_StreamProcessorManager.getNbBuffers())) + 10;
167     debugOutput(DEBUG_LEVEL_VERBOSE, "Nominal prebuffer: %u\n", packets_to_prebuffer);
168     return packets_to_prebuffer;
169 }
170
171 /***********************************************
172  * Buffer management and manipulation          *
173  ***********************************************/
174
175 int StreamProcessor::getBufferFill() {
176     return m_data_buffer->getBufferFill();
177 }
178
179 int64_t
180 StreamProcessor::getTimeUntilNextPeriodSignalUsecs()
181 {
182     uint64_t time_at_period=getTimeAtPeriod();
183
184     // we delay the period signal with the sync delay
185     // this makes that the period signals lag a little compared to reality
186     // ISO buffering causes the packets to be received at max
187     // m_handler->getWakeupInterval() later than the time they were received.
188     // hence their payload is available this amount of time later. However, the
189     // period boundary is predicted based upon earlier samples, and therefore can
190     // pass before these packets are processed. Adding this extra term makes that
191     // the period boundary is signalled later
192     time_at_period = addTicks(time_at_period, m_StreamProcessorManager.getSyncSource().getSyncDelay());
193
194     uint64_t cycle_timer=m_1394service.getCycleTimerTicks();
195
196     // calculate the time until the next period
197     int32_t until_next=diffTicks(time_at_period,cycle_timer);
198
199     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TAP=%11llu, CTR=%11llu, UTN=%11ld\n",
200         time_at_period, cycle_timer, until_next
201         );
202
203     // now convert to usecs
204     // don't use the mapping function because it only works
205     // for absolute times, not the relative time we are
206     // using here (which can also be negative).
207     return (int64_t)(((float)until_next) / TICKS_PER_USEC);
208 }
209
210 void
211 StreamProcessor::setSyncDelay(unsigned int d) {
212     #ifdef DEBUG
213     unsigned int frames = (unsigned int)((float)d / getTicksPerFrame());
214     debugOutput(DEBUG_LEVEL_VERBOSE, "Setting SP %p SyncDelay to %u ticks, %u frames\n", this, d, frames);
215     #endif
216     m_sync_delay = d;
217 }
218
219 unsigned int
220 StreamProcessor::getSyncDelayFrames() {
221     unsigned int frames = (unsigned int)((float)m_sync_delay / getTicksPerFrame());
222     return frames;
223 }
224
225 uint64_t
226 StreamProcessor::getTimeAtPeriodUsecs()
227 {
228     return (uint64_t)((float)getTimeAtPeriod() * TICKS_PER_USEC);
229 }
230
231 uint64_t
232 StreamProcessor::getTimeAtPeriod()
233 {
234     if (getType() == ePT_Receive) {
235         ffado_timestamp_t next_period_boundary = m_data_buffer->getTimestampFromHead(m_StreamProcessorManager.getPeriodSize());
236    
237         #ifdef DEBUG
238         ffado_timestamp_t ts;
239         signed int fc;
240         m_data_buffer->getBufferTailTimestamp(&ts,&fc);
241    
242         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD="TIMESTAMP_FORMAT_SPEC", LTS="TIMESTAMP_FORMAT_SPEC", FC=%5u, TPF=%f\n",
243             next_period_boundary, ts, fc, getTicksPerFrame()
244             );
245         #endif
246         return (uint64_t)next_period_boundary;
247     } else {
248         ffado_timestamp_t next_period_boundary = m_data_buffer->getTimestampFromTail((m_StreamProcessorManager.getNbBuffers()-1) * m_StreamProcessorManager.getPeriodSize());
249    
250         #ifdef DEBUG
251         ffado_timestamp_t ts;
252         signed int fc;
253         m_data_buffer->getBufferTailTimestamp(&ts,&fc);
254    
255         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD="TIMESTAMP_FORMAT_SPEC", LTS="TIMESTAMP_FORMAT_SPEC", FC=%5u, TPF=%f\n",
256             next_period_boundary, ts, fc, getTicksPerFrame()
257             );
258         #endif
259         return (uint64_t)next_period_boundary;
260     }
261 }
262
263 float
264 StreamProcessor::getTicksPerFrame()
265 {
266     assert(m_data_buffer != NULL);
267     return m_data_buffer->getRate();
268 }
269
270 void
271 StreamProcessor::setTicksPerFrame(float tpf)
272 {
273     assert(m_data_buffer != NULL);
274     m_data_buffer->setRate(tpf);
275 }
276
277 bool
278 StreamProcessor::setDllBandwidth(float bw)
279 {
280     m_dll_bandwidth_hz = bw;
281     return true;
282 }
283
284 bool
285 StreamProcessor::canClientTransferFrames(unsigned int nbframes)
286 {
287     bool can_transfer;
288     unsigned int fc = m_data_buffer->getFrameCounter();
289     if (getType() == ePT_Receive) {
290         can_transfer = (fc >= nbframes);
291     } else {
292         // there has to be enough space to put the frames in
293         can_transfer = m_data_buffer->getBufferSize() - fc > nbframes;
294         // or the buffer is transparent
295         can_transfer |= m_data_buffer->isTransparent();
296     }
297    
298     #ifdef DEBUG
299     if (!can_transfer) {
300         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) cannot transfer since fc == %u, nbframes == %u\n",
301             this, ePTToString(getType()), fc, nbframes);
302     }
303     #endif
304    
305     return can_transfer;
306 }
307
308 /***********************************************
309  * I/O API                                     *
310  ***********************************************/
311
312 // Packet transfer API
313 enum raw1394_iso_disposition
314 StreamProcessor::putPacket(unsigned char *data, unsigned int length,
315                            unsigned char channel, unsigned char tag, unsigned char sy,
316                            uint32_t pkt_ctr,
317                            unsigned int dropped_cycles) {
318     // bypass based upon state
319 #ifdef DEBUG
320     if (m_state == ePS_Invalid) {
321         debugError("Should not have state %s\n", ePSToString(m_state) );
322         return RAW1394_ISO_ERROR;
323     }
324 #endif
325     // FIXME: isn't this also an error condition?
326     if (m_state == ePS_Created) {
327         return RAW1394_ISO_DEFER;
328     }
329
330     if (m_state == ePS_Error) {
331         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "skip due to error state\n");
332         return RAW1394_ISO_OK;
333     }
334
335     // store the previous timestamp
336     m_last_timestamp2 = m_last_timestamp;
337
338     // NOTE: synchronized switching is restricted to a 0.5 sec span (4000 cycles)
339     //       it happens on the first 'good' cycle for the wait condition
340     //       or on the first received cycle that is received afterwards (might be a problem)
341
342     // check whether we are waiting for a stream to be disabled
343     if(m_state == ePS_WaitingForStreamDisable) {
344         // we then check whether we have to switch on this cycle
345         if (diffCycles(CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_cycle_to_switch_state) >= 0) {
346             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning\n");
347             m_next_state = ePS_DryRunning;
348             if (!updateState()) { // we are allowed to change the state directly
349                 debugError("Could not update state!\n");
350                 return RAW1394_ISO_ERROR;
351             }
352         } else {
353             // not time to disable yet
354         }
355         // the received data can be discarded while waiting for the stream
356         // to be disabled
357         // similarly for dropped packets
358         return RAW1394_ISO_OK;
359     }
360
361     // check whether we are waiting for a stream to be enabled
362     else if(m_state == ePS_WaitingForStreamEnable
363             && m_next_state == ePS_WaitingForStreamEnable) {
364         // we then check whether we have to switch on this cycle
365         if (diffCycles(CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_cycle_to_switch_state) >= 0) {
366             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to Running\n");
367             m_next_state = ePS_Running;
368             if (!updateState()) { // we are allowed to change the state directly
369                 debugError("Could not update state!\n");
370                 return RAW1394_ISO_ERROR;
371             }
372         } else {
373             // not time to enable yet
374         }
375         // we are dryRunning hence data should be processed in any case
376     }
377
378     // check the packet header
379     enum eChildReturnValue result = processPacketHeader(data, length, tag, sy, pkt_ctr);
380
381     // handle dropped cycles
382     if(dropped_cycles) {
383         // make sure the last_timestamp is corrected
384         m_correct_last_timestamp = true;
385         if (m_state == ePS_Running) {
386             // this is an xrun situation
387             m_in_xrun = true;
388             debugOutput(DEBUG_LEVEL_NORMAL, "Should update state to WaitingForStreamDisable due to dropped packet xrun\n");
389             m_cycle_to_switch_state = CYCLE_TIMER_GET_CYCLES(pkt_ctr) + 1; // switch in the next cycle
390             m_next_state = ePS_WaitingForStreamDisable;
391             // execute the requested change
392             if (!updateState()) { // we are allowed to change the state directly
393                 debugError("Could not update state!\n");
394                 return RAW1394_ISO_ERROR;
395             }
396         }
397     }
398
399     if (result == eCRV_OK) {
400         #ifdef DEBUG
401         if (m_last_timestamp > 0 && m_last_timestamp2 > 0) {
402             int64_t tsp_diff = diffTicks(m_last_timestamp, m_last_timestamp2);
403             debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "TSP diff: %lld\n", tsp_diff);
404             double tsp_diff_d = tsp_diff;
405             double fs_syt = 1.0/tsp_diff_d;
406             fs_syt *= (double)getNominalFramesPerPacket() * (double)TICKS_PER_USEC * 1e6;
407             double fs_nom = (double)m_StreamProcessorManager.getNominalRate();
408             double fs_diff = fs_nom - fs_syt;
409             double fs_diff_norm = fs_diff/fs_nom;
410             debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "Nom fs: %12f, Instantanous fs: %12f, diff: %12f (%12f)\n",
411                         fs_nom, fs_syt, fs_diff, fs_diff_norm);
412             if (fs_diff_norm > 0.01 || fs_diff_norm < -0.01) {
413                 debugWarning( "Instantanous samplerate more than 1%% off nominal. [Nom fs: %12f, Instantanous fs: %12f, diff: %12f (%12f)]\n",
414                         fs_nom, fs_syt, fs_diff, fs_diff_norm);
415             }
416         }
417         #endif
418
419 //         #ifdef DEBUG
420         int ticks_per_packet = (int)(getTicksPerFrame() * getNominalFramesPerPacket());
421         int diff = diffTicks(m_last_timestamp, m_last_timestamp2);
422         // display message if the difference between two successive tick
423         // values is more than 50 ticks. 1 sample at 48k is 512 ticks
424         // so 50 ticks = 10%, which is a rather large jitter value.
425         if(diff-ticks_per_packet > 50 || diff-ticks_per_packet < -50) {
426             debugOutput(DEBUG_LEVEL_VERBOSE,
427                         "cy %04u rather large TSP difference TS=%011llu => TS=%011llu (%d, nom %d)\n",
428                         CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_last_timestamp2,
429                         m_last_timestamp, diff, ticks_per_packet);
430             // !!!HACK!!! FIXME: this is the result of a failure in wrapping/unwrapping somewhere
431             // it's definitely a bug.
432             // try to fix up the timestamp
433             int64_t last_timestamp_fixed;
434             // first try to add one second
435             last_timestamp_fixed = addTicks(m_last_timestamp, TICKS_PER_SECOND);
436             diff = diffTicks(last_timestamp_fixed, m_last_timestamp2);
437             if(diff-ticks_per_packet < 50 && diff-ticks_per_packet > -50) {
438                 debugWarning("cy %04u rather large TSP difference TS=%011llu => TS=%011llu (%d, nom %d)\n",
439                              CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_last_timestamp2,
440                              m_last_timestamp, diff, ticks_per_packet);
441                 debugWarning("HACK: fixed by adding one second of ticks. This is a bug being run-time fixed.\n");
442                 m_last_timestamp = last_timestamp_fixed;
443             } else {
444                 // if that didn't work, try to subtract one second
445                 last_timestamp_fixed = substractTicks(m_last_timestamp, TICKS_PER_SECOND);
446                 diff = diffTicks(last_timestamp_fixed, m_last_timestamp2);
447                 if(diff-ticks_per_packet < 50 && diff-ticks_per_packet > -50) {
448                     debugWarning("cy %04u rather large TSP difference TS=%011llu => TS=%011llu (%d, nom %d)\n",
449                                 CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_last_timestamp2,
450                                 m_last_timestamp, diff, ticks_per_packet);
451                     debugWarning("HACK: fixed by subtracing one second of ticks. This is a bug being run-time fixed.\n");
452                     m_last_timestamp = last_timestamp_fixed;
453                 }
454             }
455         }
456         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
457                            "%04u %011llu %011llu %d %d\n",
458                            CYCLE_TIMER_GET_CYCLES(pkt_ctr),
459                            m_last_timestamp2, m_last_timestamp,
460                            diff, ticks_per_packet);
461 //         #endif
462
463         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
464                           "RECV: CY=%04u TS=%011llu\n",
465                           CYCLE_TIMER_GET_CYCLES(pkt_ctr),
466                           m_last_timestamp);
467
468         if(m_correct_last_timestamp) {
469             // they represent a discontinuity in the timestamps, and hence are
470             // to be dealt with
471             debugOutput(DEBUG_LEVEL_NORMAL, "(%p) Correcting timestamp for dropped cycles, discarding packet...\n", this);
472             m_data_buffer->setBufferTailTimestamp(substractTicks(m_last_timestamp,
473                                                                  (uint64_t)(getNominalFramesPerPacket()
474                                                                             * getTicksPerFrame())));
475             m_correct_last_timestamp = false;
476         }
477
478         // check whether we are waiting for a stream to startup
479         // this requires that the packet is good
480         if(m_state == ePS_WaitingForStream) {
481             // since we have a packet with an OK header,
482             // we can indicate that the stream started up
483
484             // we then check whether we have to switch on this cycle
485             if (diffCycles(CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_cycle_to_switch_state) >= 0) {
486                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning due to good packet\n");
487                 // hence go to the dryRunning state
488                 m_next_state = ePS_DryRunning;
489                 if (!updateState()) { // we are allowed to change the state directly
490                     debugError("Could not update state!\n");
491                     return RAW1394_ISO_ERROR;
492                 }
493             } else {
494                 // not time (yet) to switch state
495             }
496             // in both cases we don't want to process the data
497             return RAW1394_ISO_OK;
498         }
499
500         // check whether a state change has been requested
501         // note that only the wait state changes are synchronized with the cycles
502         else if(m_state != m_next_state) {
503             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
504                                              ePSToString(m_state), ePSToString(m_next_state));
505             // execute the requested change
506             if (!updateState()) { // we are allowed to change the state directly
507                 debugError("Could not update state!\n");
508                 return RAW1394_ISO_ERROR;
509             }
510         }
511
512         // for all states that reach this we are allowed to
513         // do protocol specific data reception
514         enum eChildReturnValue result2 = processPacketData(data, length);
515
516         // if an xrun occured, switch to the dryRunning state and
517         // allow for the xrun to be picked up
518         if (result2 == eCRV_XRun) {
519             debugOutput(DEBUG_LEVEL_NORMAL, "processPacketData xrun\n");
520             m_in_xrun = true;
521             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to data xrun\n");
522             m_cycle_to_switch_state = CYCLE_TIMER_GET_CYCLES(pkt_ctr)+1; // switch in the next cycle
523             m_next_state = ePS_WaitingForStreamDisable;
524             // execute the requested change
525             if (!updateState()) { // we are allowed to change the state directly
526                 debugError("Could not update state!\n");
527                 return RAW1394_ISO_ERROR;
528             }
529             return RAW1394_ISO_DEFER;
530         } else if(result2 == eCRV_OK) {
531             return RAW1394_ISO_OK;
532         } else {
533             debugError("Invalid response\n");
534             return RAW1394_ISO_ERROR;
535         }
536     } else if(result == eCRV_Invalid) {
537         // apparently we don't have to do anything when the packets are not valid
538         return RAW1394_ISO_OK;
539     } else {
540         debugError("Invalid response\n");
541         return RAW1394_ISO_ERROR;
542     }
543     debugError("reached the unreachable\n");
544     return RAW1394_ISO_ERROR;
545 }
546
547 enum raw1394_iso_disposition
548 StreamProcessor::getPacket(unsigned char *data, unsigned int *length,
549                            unsigned char *tag, unsigned char *sy,
550                            uint32_t pkt_ctr, unsigned int dropped_cycles,
551                            unsigned int skipped, unsigned int max_length) {
552     if (pkt_ctr == 0xFFFFFFFF) {
553         *tag = 0;
554         *sy = 0;
555         *length = 0;
556         return RAW1394_ISO_OK;
557     }
558
559     if (m_state == ePS_Error) {
560         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "skip due to error state\n");
561         return RAW1394_ISO_OK;
562     }
563
564     uint64_t prev_timestamp;
565     // note that we can ignore skipped cycles since
566     // the protocol will take care of that
567     if (dropped_cycles > 0) {
568         // HACK: this should not be necessary, since the header generation functions should trigger the xrun.
569         //       but apparently there are some issues with the 1394 stack
570         m_in_xrun = true;
571         if(m_state == ePS_Running) {
572             debugShowBackLogLines(200);
573             debugOutput(DEBUG_LEVEL_NORMAL, "dropped packets xrun (%u)\n", dropped_cycles);
574             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to dropped packets xrun\n");
575             m_cycle_to_switch_state = CYCLE_TIMER_GET_CYCLES(pkt_ctr) + 1;
576             m_next_state = ePS_WaitingForStreamDisable;
577             // execute the requested change
578             if (!updateState()) { // we are allowed to change the state directly
579                 debugError("Could not update state!\n");
580                 return RAW1394_ISO_ERROR;
581             }
582             goto send_empty_packet;
583         }
584     }
585
586 #ifdef DEBUG
587     // bypass based upon state
588     if (m_state == ePS_Invalid) {
589         debugError("Should not have state %s\n", ePSToString(m_state) );
590         return RAW1394_ISO_ERROR;
591     }
592 #endif
593
594     // FIXME: can this happen?
595     if (m_state == ePS_Created) {
596         *tag = 0;
597         *sy = 0;
598         *length = 0;
599         return RAW1394_ISO_DEFER;
600     }
601
602     // normal processing
603
604     // store the previous timestamp
605     // keep the old value here, update m_last_timestamp2 only when
606     // a valid packet will be sent
607     prev_timestamp = m_last_timestamp;
608
609     // NOTE: synchronized switching is restricted to a 0.5 sec span (4000 cycles)
610     //       it happens on the first 'good' cycle for the wait condition
611     //       or on the first received cycle that is received afterwards (might be a problem)
612
613     // check whether we are waiting for a stream to be disabled
614     if(m_state == ePS_WaitingForStreamDisable) {
615         // we then check whether we have to switch on this cycle
616         if (diffCycles(CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_cycle_to_switch_state) >= 0) {
617             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning\n");
618             m_next_state = ePS_DryRunning;
619             if (!updateState()) { // we are allowed to change the state directly
620                 debugError("Could not update state!\n");
621                 return RAW1394_ISO_ERROR;
622             }
623         }
624         // generate the silent packet header
625         enum eChildReturnValue result = generateSilentPacketHeader(data, length, tag, sy, pkt_ctr);
626         if (result == eCRV_Packet) {
627             debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
628                                "XMIT SILENT: CY=%04u TS=%011llu\n",
629                                CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_last_timestamp);
630
631             // assumed not to xrun
632             generateSilentPacketData(data, length);
633             return RAW1394_ISO_OK;
634         // FIXME: PP: I think this [empty packet] should also be a possibility
635         // JMW: yes, it should.  MOTU needs it for a clean shutdown.
636         } else if (result == eCRV_EmptyPacket) {
637             goto send_empty_packet;
638         } else {
639             debugError("Invalid return value: %d\n", result);
640             return RAW1394_ISO_ERROR;
641         }
642     }
643     // check whether we are waiting for a stream to be enabled
644     else if(m_state == ePS_WaitingForStreamEnable
645             && m_next_state == ePS_WaitingForStreamEnable) {
646         // we then check whether we have to switch on this cycle
647         if (diffCycles(CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_cycle_to_switch_state) >= 0) {
648             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to Running\n");
649             m_next_state = ePS_Running;
650             if (!updateState()) { // we are allowed to change the state directly
651                 debugError("Could not update state!\n");
652                 return RAW1394_ISO_ERROR;
653             }
654         } else {
655             // not time to enable yet
656         }
657         // we are dryRunning hence data should be processed in any case
658     }
659     // check whether we are waiting for a stream to startup
660     else if(m_state == ePS_WaitingForStream) {
661         // check whether we have to switch on this cycle
662         if ((diffCycles(CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_cycle_to_switch_state) >= 0)) {
663             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStream to DryRunning\n");
664             // hence go to the dryRunning state
665             m_next_state = ePS_DryRunning;
666             if (!updateState()) { // we are allowed to change the state directly
667                 debugError("Could not update state!\n");
668                 return RAW1394_ISO_ERROR;
669             }
670         } else {
671             // not time (yet) to switch state
672         }
673     }
674     else if(m_state == ePS_Running) {
675         // check the packet header
676         enum eChildReturnValue result = generatePacketHeader(data, length, tag, sy, pkt_ctr);
677         if (result == eCRV_Packet || result == eCRV_Defer) {
678             debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
679                                "XMIT: CY=%04u TS=%011llu\n",
680                                CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_last_timestamp);
681
682             // valid packet timestamp
683             m_last_timestamp2 = prev_timestamp;
684
685             // check whether a state change has been requested
686             // note that only the wait state changes are synchronized with the cycles
687             if(m_state != m_next_state) {
688                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
689                                                 ePSToString(m_state), ePSToString(m_next_state));
690                 // execute the requested change
691                 if (!updateState()) { // we are allowed to change the state directly
692                     debugError("Could not update state!\n");
693                     return RAW1394_ISO_ERROR;
694                 }
695             }
696
697             enum eChildReturnValue result2 = generatePacketData(data, length);
698             // if an xrun occured, switch to the dryRunning state and
699             // allow for the xrun to be picked up
700             if (result2 == eCRV_XRun) {
701                 debugOutput(DEBUG_LEVEL_NORMAL, "generatePacketData xrun\n");
702                 m_in_xrun = true;
703                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to data xrun\n");
704                 m_cycle_to_switch_state = CYCLE_TIMER_GET_CYCLES(pkt_ctr) + 1; // switch in the next cycle
705                 m_next_state = ePS_WaitingForStreamDisable;
706                 // execute the requested change
707                 if (!updateState()) { // we are allowed to change the state directly
708                     debugError("Could not update state!\n");
709                     return RAW1394_ISO_ERROR;
710                 }
711                 goto send_empty_packet;
712             }
713             #ifdef DEBUG
714             if (m_last_timestamp > 0 && m_last_timestamp2 > 0) {
715                 int64_t tsp_diff = diffTicks(m_last_timestamp, m_last_timestamp2);
716                 debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "TSP diff: %lld\n", tsp_diff);
717                 double tsp_diff_d = tsp_diff;
718                 double fs_syt = 1.0/tsp_diff_d;
719                 fs_syt *= (double)getNominalFramesPerPacket() * (double)TICKS_PER_USEC * 1e6;
720                 double fs_nom = (double)m_StreamProcessorManager.getNominalRate();
721                 double fs_diff = fs_nom - fs_syt;
722                 double fs_diff_norm = fs_diff/fs_nom;
723                 debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "Nom fs: %12f, Instantanous fs: %12f, diff: %12f (%12f)\n",
724                            fs_nom, fs_syt, fs_diff, fs_diff_norm);
725                 if (fs_diff_norm > 0.01 || fs_diff_norm < -0.01) {
726                     debugWarning( "Instantanous samplerate more than 1%% off nominal. [Nom fs: %12f, Instantanous fs: %12f, diff: %12f (%12f)]\n",
727                            fs_nom, fs_syt, fs_diff, fs_diff_norm);
728                 }
729                 int ticks_per_packet = (int)(getTicksPerFrame() * getNominalFramesPerPacket());
730                 int diff = diffTicks(m_last_timestamp, m_last_timestamp2);
731                 // display message if the difference between two successive tick
732                 // values is more than 50 ticks. 1 sample at 48k is 512 ticks
733                 // so 50 ticks = 10%, which is a rather large jitter value.
734                 if(diff-ticks_per_packet > 50 || diff-ticks_per_packet < -50) {
735                     debugOutput(DEBUG_LEVEL_VERBOSE,
736                                 "cy %04d, rather large TSP difference TS=%011llu => TS=%011llu (%d, nom %d)\n",
737                                 CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_last_timestamp2,
738                                 m_last_timestamp, diff, ticks_per_packet);
739                 }
740                 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
741                                 "%04d %011llu %011llu %d %d\n",
742                                 CYCLE_TIMER_GET_CYCLES(pkt_ctr), m_last_timestamp2,
743                                 m_last_timestamp, diff, ticks_per_packet);
744             }
745             #endif
746
747             // skip queueing packets if we detect that there are not enough frames
748             // available
749             if(result2 == eCRV_Defer || result == eCRV_Defer) {
750                 return RAW1394_ISO_DEFER;
751             } else {
752                 return RAW1394_ISO_OK;
753             }
754         } else if (result == eCRV_XRun) { // pick up the possible xruns
755             debugOutput(DEBUG_LEVEL_NORMAL, "generatePacketHeader xrun\n");
756             m_in_xrun = true;
757             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to header xrun\n");
758             m_cycle_to_switch_state = CYCLE_TIMER_GET_CYCLES(pkt_ctr) + 1; // switch in the next cycle
759             m_next_state = ePS_WaitingForStreamDisable;
760             // execute the requested change
761             if (!updateState()) { // we are allowed to change the state directly
762                 debugError("Could not update state!\n");
763                 return RAW1394_ISO_ERROR;
764             }
765         } else if (result == eCRV_EmptyPacket) {
766             if(m_state != m_next_state) {
767                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
768                                                 ePSToString(m_state), ePSToString(m_next_state));
769                 // execute the requested change
770                 if (!updateState()) { // we are allowed to change the state directly
771                     debugError("Could not update state!\n");
772                     return RAW1394_ISO_ERROR;
773                 }
774             }
775             goto send_empty_packet;
776         } else if (result == eCRV_Again) {
777             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "have to retry cycle %d\n", CYCLE_TIMER_GET_CYCLES(pkt_ctr));
778             if(m_state != m_next_state) {
779                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
780                                                 ePSToString(m_state), ePSToString(m_next_state));
781                 // execute the requested change
782                 if (!updateState()) { // we are allowed to change the state directly
783                     debugError("Could not update state!\n");
784                     return RAW1394_ISO_ERROR;
785                 }
786             }
787 //             usleep(125); // only when using thread-per-handler
788 //             return RAW1394_ISO_AGAIN;
789             generateEmptyPacketHeader(data, length, tag, sy, pkt_ctr);
790             generateEmptyPacketData(data, length);
791             return RAW1394_ISO_DEFER;
792         } else {
793             debugError("Invalid return value: %d\n", result);
794             return RAW1394_ISO_ERROR;
795         }
796     }
797     // we are not running, so send an empty packet
798     // we should generate a valid packet any time
799 send_empty_packet:
800     // note that only the wait state changes are synchronized with the cycles
801     if(m_state != m_next_state) {
802         debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
803                                         ePSToString(m_state), ePSToString(m_next_state));
804         // execute the requested change
805         if (!updateState()) { // we are allowed to change the state directly
806             debugError("Could not update state!\n");
807             return RAW1394_ISO_ERROR;
808         }
809     }
810     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
811                        "XMIT EMPTY: CY=%04u\n",
812                        CYCLE_TIMER_GET_CYCLES(pkt_ctr));
813
814     generateEmptyPacketHeader(data, length, tag, sy, pkt_ctr);
815     generateEmptyPacketData(data, length);
816     return RAW1394_ISO_OK;
817 }
818
819 // Frame Transfer API
820 /**
821  * Transfer a block of frames from the event buffer to the port buffers
822  * @param nbframes number of frames to transfer
823  * @param ts the timestamp that the LAST frame in the block should have
824  * @return
825  */
826 bool StreamProcessor::getFrames(unsigned int nbframes, int64_t ts) {
827     bool result;
828     debugOutputExtreme( DEBUG_LEVEL_VERBOSE,
829                         "(%p, %s) getFrames(%d, %11llu)\n",
830                         this, getTypeString(), nbframes, ts);
831     assert( getType() == ePT_Receive );
832     if(isDryRunning()) result = getFramesDry(nbframes, ts);
833     else result = getFramesWet(nbframes, ts);
834     SIGNAL_ACTIVITY_ISO_RECV;
835     return result;
836 }
837
838 bool StreamProcessor::getFramesWet(unsigned int nbframes, int64_t ts) {
839 // FIXME: this should be done somewhere else
840 #ifdef DEBUG
841     uint64_t ts_expected;
842     signed int fc;
843     int32_t lag_ticks;
844     float lag_frames;
845
846     // in order to sync up multiple received streams, we should
847     // use the ts parameter. It specifies the time of the block's
848     // last sample.
849     float srate = m_StreamProcessorManager.getSyncSource().getTicksPerFrame();
850     assert(srate != 0.0);
851     int64_t this_block_length_in_ticks = (int64_t)(((float)nbframes) * srate);
852
853     ffado_timestamp_t ts_head_tmp;
854     m_data_buffer->getBufferHeadTimestamp(&ts_head_tmp, &fc);
855     ts_expected = addTicks((uint64_t)ts_head_tmp, this_block_length_in_ticks);
856
857     lag_ticks = diffTicks(ts, ts_expected);
858     lag_frames = (((float)lag_ticks) / srate);
859     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
860                        "stream (%p): drifts %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
861                        this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
862     if (lag_frames >= 1.0) {
863         // the stream lags
864         debugOutput(DEBUG_LEVEL_VERBOSE, "stream (%p): lags  with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
865                       this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
866     } else if (lag_frames <= -1.0) {
867         // the stream leads
868         debugOutput(DEBUG_LEVEL_VERBOSE, "stream (%p): leads with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
869                       this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
870     }
871 #endif
872     // ask the buffer to process nbframes of frames
873     // using it's registered client's processReadBlock(),
874     // which should be ours
875     m_data_buffer->blockProcessReadFrames(nbframes);
876     return true;
877 }
878
879 bool StreamProcessor::getFramesDry(unsigned int nbframes, int64_t ts)
880 {
881     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
882                        "stream (%p): dry run %d frames (@ ts=%lld)\n",
883                        this, nbframes, ts);
884     // dry run on this side means that we put silence in all enabled ports
885     // since there is do data put into the ringbuffer in the dry-running state
886     return provideSilenceBlock(nbframes, 0);
887 }
888
889 bool
890 StreamProcessor::dropFrames(unsigned int nbframes, int64_t ts)
891 {
892     bool result;
893     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "StreamProcessor::dropFrames(%d, %lld)\n", nbframes, ts);
894     result = m_data_buffer->dropFrames(nbframes);
895     SIGNAL_ACTIVITY_ISO_RECV;
896     return result;
897 }
898
899 bool StreamProcessor::putFrames(unsigned int nbframes, int64_t ts)
900 {
901     bool result;
902     debugOutputExtreme( DEBUG_LEVEL_VERBOSE,
903                         "(%p, %s) putFrames(%d, %11llu)\n",
904                         this, getTypeString(), nbframes, ts);
905     assert( getType() == ePT_Transmit );
906     if(isDryRunning()) result = putFramesDry(nbframes, ts);
907     else result = putFramesWet(nbframes, ts);
908     SIGNAL_ACTIVITY_ISO_XMIT;
909     return result;
910 }
911
912 bool
913 StreamProcessor::putFramesWet(unsigned int nbframes, int64_t ts)
914 {
915     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
916                        "StreamProcessor::putFramesWet(%d, %llu)\n",
917                        nbframes, ts);
918     // transfer the data
919     m_data_buffer->blockProcessWriteFrames(nbframes, ts);
920     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
921                        " New timestamp: %llu\n", ts);
922     return true; // FIXME: what about failure?
923 }
924
925 bool
926 StreamProcessor::putFramesDry(unsigned int nbframes, int64_t ts)
927 {
928     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
929                        "StreamProcessor::putFramesDry(%d, %llu)\n",
930                        nbframes, ts);
931     // do nothing
932     return true;
933 }
934
935 bool
936 StreamProcessor::putSilenceFrames(unsigned int nbframes, int64_t ts)
937 {
938     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
939                        "StreamProcessor::putSilenceFrames(%d, %llu)\n",
940                        nbframes, ts);
941
942     size_t bytes_per_frame = getEventSize() * getEventsPerFrame();
943     unsigned int scratch_buffer_size_frames = m_scratch_buffer_size_bytes / bytes_per_frame;
944
945     if (nbframes > scratch_buffer_size_frames) {
946         debugError("nframes (%u) > scratch_buffer_size_frames (%u)\n",
947                    nbframes, scratch_buffer_size_frames);
948     }
949
950     assert(m_scratch_buffer);
951     if(!transmitSilenceBlock((char *)m_scratch_buffer, nbframes, 0)) {
952         debugError("Could not prepare silent block\n");
953         return false;
954     }
955     if(!m_data_buffer->writeFrames(nbframes, (char *)m_scratch_buffer, ts)) {
956         debugError("Could not write silent block\n");
957         return false;
958     }
959
960     SIGNAL_ACTIVITY_ISO_XMIT;
961     return true;
962 }
963
964 bool
965 StreamProcessor::shiftStream(int nbframes)
966 {
967     // FIXME: this is not a good idea since the ISO thread is also writing the buffer
968     // resulting in multiple writers (not supported)
969     bool result;
970     if(nbframes == 0) return true;
971     if(nbframes > 0) {
972         debugOutput(DEBUG_LEVEL_VERBOSE,
973                     "(%p) dropping %d frames\n",
974                     this, nbframes);
975         result = m_data_buffer->dropFrames(nbframes);
976     } else {
977         result = false;
978         return result;
979         debugOutput(DEBUG_LEVEL_VERBOSE,
980                     "(%p) adding %d frames\n",
981                     this, nbframes);
982         while(nbframes++) {
983             result &= m_data_buffer->writeDummyFrame();
984         }
985     }
986     SIGNAL_ACTIVITY_ALL;
987     return result;
988 }
989
990 /**
991  * @brief write silence events to the stream ringbuffers.
992  */
993 bool StreamProcessor::provideSilenceBlock(unsigned int nevents, unsigned int offset)
994 {
995     bool no_problem=true;
996     for ( PortVectorIterator it = m_Ports.begin();
997           it != m_Ports.end();
998           ++it ) {
999         if((*it)->isDisabled()) {continue;};
1000
1001         if(provideSilenceToPort((*it), offset, nevents)) {
1002             debugWarning("Could not put silence into to port %s",(*it)->getName().c_str());
1003             no_problem=false;
1004         }
1005     }
1006     return no_problem;
1007 }
1008
1009 int
1010 StreamProcessor::provideSilenceToPort(Port *p, unsigned int offset, unsigned int nevents)
1011 {
1012     unsigned int j=0;
1013     switch(p->getPortType()) {
1014         default:
1015             debugError("Invalid port type: %d\n", p->getPortType());
1016             return -1;
1017         case Port::E_Midi:
1018         case Port::E_Control:
1019             {
1020                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
1021                 assert(nevents + offset <= p->getBufferSize());
1022                 buffer+=offset;
1023
1024                 for(j = 0; j < nevents; j += 1) {
1025                     *(buffer)=0;
1026                     buffer++;
1027                 }
1028             }
1029             break;
1030         case Port::E_Audio:
1031             switch(m_StreamProcessorManager.getAudioDataType()) {
1032             case StreamProcessorManager::eADT_Int24:
1033                 {
1034                     quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
1035                     assert(nevents + offset <= p->getBufferSize());
1036                     buffer+=offset;
1037    
1038                     for(j = 0; j < nevents; j += 1) {
1039                         *(buffer)=0;
1040                         buffer++;
1041                     }
1042                 }
1043                 break;
1044             case StreamProcessorManager::eADT_Float:
1045                 {
1046                     float *buffer=(float *)(p->getBufferAddress());
1047                     assert(nevents + offset <= p->getBufferSize());
1048                     buffer+=offset;
1049    
1050                     for(j = 0; j < nevents; j += 1) {
1051                         *buffer = 0.0;
1052                         buffer++;
1053                     }
1054                 }
1055                 break;
1056             }
1057             break;
1058     }
1059     return 0;
1060 }
1061
1062 /***********************************************
1063  * State related API                           *
1064  ***********************************************/
1065 bool StreamProcessor::init()
1066 {
1067     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "init...\n");
1068
1069     if(!m_IsoHandlerManager.registerStream(this)) {
1070         debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register stream processor with the Iso manager\n");
1071         return false;
1072     }
1073     if(!m_StreamProcessorManager.registerProcessor(this)) {
1074         debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register stream processor with the SP manager\n");
1075         return false;
1076     }
1077
1078     // initialization can be done without requesting it
1079     // from the packet loop
1080     m_next_state = ePS_Created;
1081     return true;
1082 }
1083
1084 bool StreamProcessor::prepare()
1085 {
1086     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare SP (%p)...\n", this);
1087
1088     // make the scratch buffer one period of frames long
1089     m_scratch_buffer_size_bytes = m_StreamProcessorManager.getPeriodSize() * getEventsPerFrame() * getEventSize();
1090     debugOutput( DEBUG_LEVEL_VERBOSE, " Allocate scratch buffer of %d quadlets\n");
1091     if(m_scratch_buffer) delete[] m_scratch_buffer;
1092     m_scratch_buffer = new byte_t[m_scratch_buffer_size_bytes];
1093     if(m_scratch_buffer == NULL) {
1094         debugFatal("Could not allocate scratch buffer\n");
1095         return false;
1096     }
1097
1098     // set the parameters of ports we can:
1099     // we want the audio ports to be period buffered,
1100     // and the midi ports to be packet buffered
1101     for ( PortVectorIterator it = m_Ports.begin();
1102         it != m_Ports.end();
1103         ++it )
1104     {
1105         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
1106         if(!(*it)->setBufferSize(m_StreamProcessorManager.getPeriodSize())) {
1107             debugFatal("Could not set buffer size to %d\n",m_StreamProcessorManager.getPeriodSize());
1108             return false;
1109         }
1110     }
1111     // the API specific settings of the ports should already be set,
1112     // as this is called from the processorManager->prepare()
1113     // so we can init the ports
1114     if(!PortManager::initPorts()) {
1115         debugFatal("Could not initialize ports\n");
1116         return false;
1117     }
1118
1119     if (!prepareChild()) {
1120         debugFatal("Could not prepare child\n");
1121         return false;
1122     }
1123
1124     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n");
1125     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d  [DLL Bandwidth: %f Hz]\n",
1126              m_StreamProcessorManager.getNominalRate(), m_dll_bandwidth_hz);
1127     debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n",
1128              m_StreamProcessorManager.getPeriodSize(), m_StreamProcessorManager.getNbBuffers());
1129     debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n",
1130              m_1394service.getPort(), m_channel);
1131
1132     // initialization can be done without requesting it
1133     // from the packet loop
1134     m_next_state = ePS_Stopped;
1135     return updateState();
1136 }
1137
1138 bool
1139 StreamProcessor::scheduleStateTransition(enum eProcessorState state, uint64_t time_instant)
1140 {
1141     // first set the time, since in the packet loop we first check m_state == m_next_state before
1142     // using the time
1143     m_cycle_to_switch_state = TICKS_TO_CYCLES(time_instant);
1144     m_next_state = state;
1145     // wake up any threads that might be waiting on data in the buffers
1146     // since a state transition can cause data to become available
1147     SIGNAL_ACTIVITY_ALL;
1148     return true;
1149 }
1150
1151 bool
1152 StreamProcessor::waitForState(enum eProcessorState state, unsigned int timeout_ms)
1153 {
1154     debugOutput(DEBUG_LEVEL_VERBOSE, "Waiting for state %s\n", ePSToString(state));
1155     int cnt = timeout_ms;
1156     while (m_state != state && cnt) {
1157         SleepRelativeUsec(1000);
1158         cnt--;
1159     }
1160     if(cnt==0) {
1161         debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout\n");
1162         return false;
1163     }
1164     return true;
1165 }
1166
1167 bool StreamProcessor::scheduleStartDryRunning(int64_t t) {
1168     uint64_t tx;
1169     if (t < 0) {
1170         tx = addTicks(m_1394service.getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
1171     } else {
1172         tx = t;
1173     }
1174     uint64_t start_handler_ticks = substractTicks(tx, 100 * TICKS_PER_CYCLE);
1175
1176     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
1177     #ifdef DEBUG
1178     uint64_t now = m_1394service.getCycleTimerTicks();
1179     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
1180                           now,
1181                           (unsigned int)TICKS_TO_SECS(now),
1182                           (unsigned int)TICKS_TO_CYCLES(now),
1183                           (unsigned int)TICKS_TO_OFFSET(now));
1184     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%03us %04uc %04ut)\n",
1185                           tx,
1186                           (unsigned int)TICKS_TO_SECS(tx),
1187                           (unsigned int)TICKS_TO_CYCLES(tx),
1188                           (unsigned int)TICKS_TO_OFFSET(tx));
1189     #endif
1190     if (m_state == ePS_Stopped) {
1191         if(!m_IsoHandlerManager.startHandlerForStream(
1192                                         this, TICKS_TO_CYCLES(start_handler_ticks))) {
1193             debugError("Could not start handler for SP %p\n", this);
1194             return false;
1195         }
1196         return scheduleStateTransition(ePS_WaitingForStream, tx);
1197     } else if (m_state == ePS_Running) {
1198         return scheduleStateTransition(ePS_WaitingForStreamDisable, tx);
1199     } else if (m_state == ePS_DryRunning) {
1200         debugOutput(DEBUG_LEVEL_VERBOSE, " %p already in DryRunning state\n", this);
1201         return true;
1202     } else if (m_state == ePS_WaitingForStreamEnable) {
1203         debugOutput(DEBUG_LEVEL_VERBOSE, " %p still waiting to switch to Running state\n", this);
1204         // this will happen immediately
1205         return scheduleStateTransition(ePS_DryRunning, tx);
1206     } else if (m_state == ePS_WaitingForStreamDisable) {
1207         debugOutput(DEBUG_LEVEL_VERBOSE, " %p already waiting to switch to DryRunning state\n", this);
1208         return true;
1209     } else {
1210         debugError("Cannot switch to ePS_DryRunning from %s\n", ePSToString(m_state));
1211         return false;
1212     }
1213 }
1214
1215 bool StreamProcessor::scheduleStartRunning(int64_t t) {
1216     uint64_t tx;
1217     if (t < 0) {
1218         tx = addTicks(m_1394service.getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
1219     } else {
1220         tx = t;
1221     }
1222     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
1223     #ifdef DEBUG
1224     uint64_t now = m_1394service.getCycleTimerTicks();
1225     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
1226                           now,
1227                           (unsigned int)TICKS_TO_SECS(now),
1228                           (unsigned int)TICKS_TO_CYCLES(now),
1229                           (unsigned int)TICKS_TO_OFFSET(now));
1230     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%03us %04uc %04ut)\n",
1231                           tx,
1232                           (unsigned int)TICKS_TO_SECS(tx),
1233                           (unsigned int)TICKS_TO_CYCLES(tx),
1234                           (unsigned int)TICKS_TO_OFFSET(tx));
1235     #endif
1236     return scheduleStateTransition(ePS_WaitingForStreamEnable, tx);
1237 }
1238
1239 bool StreamProcessor::scheduleStopDryRunning(int64_t t) {
1240     uint64_t tx;
1241     if (t < 0) {
1242         tx = addTicks(m_1394service.getCycleTimerTicks(), 2000 * TICKS_PER_CYCLE);
1243     } else {
1244         tx = t;
1245     }
1246     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
1247     #ifdef DEBUG
1248     uint64_t now = m_1394service.getCycleTimerTicks();
1249     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
1250                           now,
1251                           (unsigned int)TICKS_TO_SECS(now),
1252                           (unsigned int)TICKS_TO_CYCLES(now),
1253                           (unsigned int)TICKS_TO_OFFSET(now));
1254     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at              : %011llu (%03us %04uc %04ut)\n",
1255                           tx,
1256                           (unsigned int)TICKS_TO_SECS(tx),
1257                           (unsigned int)TICKS_TO_CYCLES(tx),
1258                           (unsigned int)TICKS_TO_OFFSET(tx));
1259     #endif
1260
1261     return scheduleStateTransition(ePS_Stopped, tx);
1262 }
1263
1264 bool StreamProcessor::scheduleStopRunning(int64_t t) {
1265     uint64_t tx;
1266     if (t < 0) {
1267         tx = addTicks(m_1394service.getCycleTimerTicks(), 2000 * TICKS_PER_CYCLE);
1268     } else {
1269         tx = t;
1270     }
1271     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
1272     #ifdef DEBUG
1273     uint64_t now = m_1394service.getCycleTimerTicks();
1274     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
1275                           now,
1276                           (unsigned int)TICKS_TO_SECS(now),
1277                           (unsigned int)TICKS_TO_CYCLES(now),
1278                           (unsigned int)TICKS_TO_OFFSET(now));
1279     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at              : %011llu (%03us %04uc %04ut)\n",
1280                           tx,
1281                           (unsigned int)TICKS_TO_SECS(tx),
1282                           (unsigned int)TICKS_TO_CYCLES(tx),
1283                           (unsigned int)TICKS_TO_OFFSET(tx));
1284     #endif
1285     return scheduleStateTransition(ePS_WaitingForStreamDisable, tx);
1286 }
1287
1288 bool StreamProcessor::startDryRunning(int64_t t) {
1289     if(getState() == ePS_DryRunning) {
1290         // already in the correct state
1291         return true;
1292     }
1293     if(!scheduleStartDryRunning(t)) {
1294         debugError("Could not schedule transition\n");
1295         return false;
1296     }
1297     if(!waitForState(ePS_DryRunning, 2000)) {
1298         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_DryRunning));
1299         return false;
1300     }
1301     return true;
1302 }
1303
1304 bool StreamProcessor::startRunning(int64_t t) {
1305     if(getState() == ePS_Running) {
1306         // already in the correct state
1307         return true;
1308     }
1309     if(!scheduleStartRunning(t)) {
1310         debugError("Could not schedule transition\n");
1311         return false;
1312     }
1313     if(!waitForState(ePS_Running, 2000)) {
1314         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_Running));
1315         return false;
1316     }
1317     return true;
1318 }
1319
1320 bool StreamProcessor::stopDryRunning(int64_t t) {
1321     if(getState() == ePS_Stopped) {
1322         // already in the correct state
1323         return true;
1324     }
1325     if(!scheduleStopDryRunning(t)) {
1326         debugError("Could not schedule transition\n");
1327         return false;
1328     }
1329     if(!waitForState(ePS_Stopped, 2000)) {
1330         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_Stopped));
1331         return false;
1332     }
1333     return true;
1334 }
1335
1336 bool StreamProcessor::stopRunning(int64_t t) {
1337     if(getState() == ePS_DryRunning) {
1338         // already in the correct state
1339         return true;
1340     }
1341     if(!scheduleStopRunning(t)) {
1342         debugError("Could not schedule transition\n");
1343         return false;
1344     }
1345     if(!waitForState(ePS_DryRunning, 2000)) {
1346         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_DryRunning));
1347         return false;
1348     }
1349     return true;
1350 }
1351
1352
1353 // internal state API
1354
1355 /**
1356  * @brief Enter the ePS_Stopped state
1357  * @return true if successful, false if not
1358  *
1359  * @pre none
1360  *
1361  * @post the buffer and the isostream are ready for use.
1362  * @post all dynamic structures have been allocated successfully
1363  * @post the buffer is transparent and empty, and all parameters are set
1364  *       to the correct initial/nominal values.
1365  *
1366  */
1367 bool
1368 StreamProcessor::doStop()
1369 {
1370     float ticks_per_frame;
1371     unsigned int ringbuffer_size_frames = (m_StreamProcessorManager.getNbBuffers() + 1) * m_StreamProcessorManager.getPeriodSize();
1372
1373     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1374     bool result = true;
1375
1376     switch(m_state) {
1377         case ePS_Created:
1378             assert(m_data_buffer);
1379
1380             // prepare the framerate estimate
1381             ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_StreamProcessorManager.getNominalRate());
1382             m_ticks_per_frame = ticks_per_frame;
1383             m_local_node_id= m_1394service.getLocalNodeId() & 0x3f;
1384             m_correct_last_timestamp = false;
1385
1386             debugOutput(DEBUG_LEVEL_VERBOSE, "Initializing remote ticks/frame to %f\n", ticks_per_frame);
1387
1388             // initialize internal buffer
1389             result &= m_data_buffer->setBufferSize(ringbuffer_size_frames);
1390
1391             result &= m_data_buffer->setEventSize( getEventSize() );
1392             result &= m_data_buffer->setEventsPerFrame( getEventsPerFrame() );
1393             if(getType() == ePT_Receive) {
1394                 result &= m_data_buffer->setUpdatePeriod( getNominalFramesPerPacket() );
1395             } else {
1396                 result &= m_data_buffer->setUpdatePeriod( m_StreamProcessorManager.getPeriodSize() );
1397             }
1398             result &= m_data_buffer->setNominalRate(ticks_per_frame);
1399             result &= m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND);
1400             result &= m_data_buffer->setBandwidth(STREAMPROCESSOR_DLL_FAST_BW_HZ / (double)TICKS_PER_SECOND);
1401             result &= m_data_buffer->prepare(); // FIXME: the name
1402
1403             debugOutput(DEBUG_LEVEL_VERBOSE, "DLL info: nominal tpf: %f, update period: %d, bandwidth: %e 1/ticks (%e Hz)\n",
1404                         m_data_buffer->getNominalRate(), m_data_buffer->getUpdatePeriod(), m_data_buffer->getBandwidth(), m_data_buffer->getBandwidth() * TICKS_PER_SECOND);
1405
1406             break;
1407         case ePS_DryRunning:
1408             if(!m_IsoHandlerManager.stopHandlerForStream(this)) {
1409                 debugError("Could not stop handler for SP %p\n", this);
1410                 return false;
1411             }
1412             break;
1413         default:
1414             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1415             return false;
1416     }
1417
1418     result &= m_data_buffer->clearBuffer(); // FIXME: don't like the reset() name
1419     // make the buffer transparent
1420     m_data_buffer->setTransparent(true);
1421
1422     // reset all ports
1423     result &= PortManager::preparePorts();
1424
1425     m_state = ePS_Stopped;
1426     #ifdef DEBUG
1427     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1428         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1429         dumpInfo();
1430     }
1431     #endif
1432     SIGNAL_ACTIVITY_ALL;
1433     return result;
1434 }
1435
1436 /**
1437  * @brief Enter the ePS_WaitingForStream state
1438  * @return true if successful, false if not
1439  *
1440  * @pre all dynamic data structures are allocated successfully
1441  *
1442  * @post
1443  *
1444  */
1445 bool
1446 StreamProcessor::doWaitForRunningStream()
1447 {
1448     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1449     switch(m_state) {
1450         case ePS_Stopped:
1451             // we have to start waiting for an incoming stream
1452             // this basically means nothing, the state change will
1453             // be picked up by the packet iterator
1454             break;
1455         default:
1456             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1457             return false;
1458     }
1459     m_state = ePS_WaitingForStream;
1460     #ifdef DEBUG
1461     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1462         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1463         dumpInfo();
1464     }
1465     #endif
1466     SIGNAL_ACTIVITY_ALL;
1467     return true;
1468 }
1469
1470 /**
1471  * @brief Enter the ePS_DryRunning state
1472  * @return true if successful, false if not
1473  *
1474  * @pre
1475  *
1476  * @post
1477  *
1478  */
1479 bool
1480 StreamProcessor::doDryRunning()
1481 {
1482     bool result = true;
1483     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1484     switch(m_state) {
1485         case ePS_WaitingForStream:
1486             // a running stream has been detected
1487             debugOutput(DEBUG_LEVEL_VERBOSE,
1488                         "StreamProcessor %p started dry-running\n",
1489                         this);
1490             m_local_node_id = m_1394service.getLocalNodeId() & 0x3f;
1491             if (getType() == ePT_Receive) {
1492                 // this to ensure that there is no discontinuity when starting to
1493                 // update the DLL based upon the received packets
1494                 m_data_buffer->setBufferTailTimestamp(m_last_timestamp);
1495             } else {
1496                 // FIXME: PC=master mode will have to do something here I guess...
1497             }
1498             break;
1499         case ePS_WaitingForStreamEnable: // when xrunning at startup
1500             result &= m_data_buffer->clearBuffer();
1501             m_data_buffer->setTransparent(true);
1502             break;
1503         case ePS_WaitingForStreamDisable:
1504             result &= m_data_buffer->clearBuffer();
1505             m_data_buffer->setTransparent(true);
1506             break;
1507         default:
1508             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1509             return false;
1510     }
1511     m_state = ePS_DryRunning;
1512     #ifdef DEBUG
1513     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1514         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1515         dumpInfo();
1516     }
1517     #endif
1518     SIGNAL_ACTIVITY_ALL;
1519     return result;
1520 }
1521
1522 /**
1523  * @brief Enter the ePS_WaitingForStreamEnable state
1524  * @return true if successful, false if not
1525  *
1526  * @pre
1527  *
1528  * @post
1529  *
1530  */
1531 bool
1532 StreamProcessor::doWaitForStreamEnable()
1533 {
1534     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1535     unsigned int ringbuffer_size_frames;
1536     switch(m_state) {
1537         case ePS_DryRunning:
1538             // we have to start waiting for an incoming stream
1539             // this basically means nothing, the state change will
1540             // be picked up by the packet iterator
1541
1542             if(!m_data_buffer->clearBuffer()) {
1543                 debugError("Could not reset data buffer\n");
1544                 return false;
1545             }
1546             if (getType() == ePT_Transmit) {
1547                 ringbuffer_size_frames = m_StreamProcessorManager.getNbBuffers() * m_StreamProcessorManager.getPeriodSize();
1548
1549                 // add sync delay
1550                 int syncdelay_in_frames = m_StreamProcessorManager.getSyncSource().getSyncDelayFrames();
1551                 ringbuffer_size_frames += syncdelay_in_frames;
1552
1553                 debugOutput(DEBUG_LEVEL_VERBOSE, "Prefill transmit SP %p with %u frames\n", this, ringbuffer_size_frames);
1554                 // prefill the buffer
1555                 if(!transferSilence(ringbuffer_size_frames)) {
1556                     debugFatal("Could not prefill transmit stream\n");
1557                     return false;
1558                 }
1559             }
1560             break;
1561         default:
1562             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1563             return false;
1564     }
1565     m_state = ePS_WaitingForStreamEnable;
1566     #ifdef DEBUG
1567     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1568         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1569         dumpInfo();
1570     }
1571     #endif
1572     SIGNAL_ACTIVITY_ALL;
1573     return true;
1574 }
1575
1576 /**
1577  * @brief Enter the ePS_Running state
1578  * @return true if successful, false if not
1579  *
1580  * @pre
1581  *
1582  * @post
1583  *
1584  */
1585 bool
1586 StreamProcessor::doRunning()
1587 {
1588     bool result = true;
1589     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1590     switch(m_state) {
1591         case ePS_WaitingForStreamEnable:
1592             // a running stream has been detected
1593             debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started running\n",
1594                                              this);
1595             m_in_xrun = false;
1596             m_local_node_id = m_1394service.getLocalNodeId() & 0x3f;
1597             // reduce the DLL bandwidth to what we require
1598             result &= m_data_buffer->setBandwidth(m_dll_bandwidth_hz / (double)TICKS_PER_SECOND);
1599             // enable the data buffer
1600             m_data_buffer->setTransparent(false);
1601             m_last_timestamp2 = 0; // NOTE: no use in checking if we just started running
1602             break;
1603         default:
1604             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1605             return false;
1606     }
1607     m_state = ePS_Running;
1608     #ifdef DEBUG
1609     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1610         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1611         dumpInfo();
1612     }
1613     #endif
1614     SIGNAL_ACTIVITY_ALL;
1615     return result;
1616 }
1617
1618 /**
1619  * @brief Enter the ePS_WaitingForStreamDisable state
1620  * @return true if successful, false if not
1621  *
1622  * @pre
1623  *
1624  * @post
1625  *
1626  */
1627 bool
1628 StreamProcessor::doWaitForStreamDisable()
1629 {
1630     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1631     switch(m_state) {
1632         case ePS_Running:
1633             // the thread will do the transition
1634             break;
1635         default:
1636             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1637             return false;
1638     }
1639     m_state = ePS_WaitingForStreamDisable;
1640     #ifdef DEBUG
1641     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1642         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1643         dumpInfo();
1644     }
1645     #endif
1646     SIGNAL_ACTIVITY_ALL;
1647     return true;
1648 }
1649
1650 /**
1651  * @brief Updates the state machine and calls the necessary transition functions
1652  * @return true if successful, false if not
1653  */
1654 bool StreamProcessor::updateState() {
1655     bool result = false;
1656     // copy the current state locally since it could change value,
1657     // and that's something we don't want to happen inbetween tests
1658     // if m_next_state changes during this routine, we know for sure
1659     // that the previous state change was at least attempted correctly.
1660     enum eProcessorState next_state = m_next_state;
1661
1662     debugOutput(DEBUG_LEVEL_VERBOSE, "Do state transition: %s => %s\n",
1663         ePSToString(m_state), ePSToString(next_state));
1664
1665     if (m_state == next_state) {
1666         debugWarning("ignoring identity state update from/to %s\n", ePSToString(m_state) );
1667         return true;
1668     }
1669     // after creation, only initialization is allowed
1670     if (m_state == ePS_Created) {
1671         if(next_state != ePS_Stopped) {
1672             goto updateState_exit_with_error;
1673         }
1674         // do init here
1675         result = doStop();
1676         if (result) {return true;}
1677         else goto updateState_exit_change_failed;
1678     }
1679
1680     // after initialization, only WaitingForRunningStream is allowed
1681     if (m_state == ePS_Stopped) {
1682         if(next_state != ePS_WaitingForStream) {
1683             goto updateState_exit_with_error;
1684         }
1685         result = doWaitForRunningStream();
1686         if (result) {return true;}
1687         else goto updateState_exit_change_failed;
1688     }
1689
1690     // after WaitingForStream, only ePS_DryRunning is allowed
1691     // this means that the stream started running
1692     if (m_state == ePS_WaitingForStream) {
1693         if(next_state != ePS_DryRunning) {
1694             goto updateState_exit_with_error;
1695         }
1696         result = doDryRunning();
1697         if (result) {return true;}
1698         else goto updateState_exit_change_failed;
1699     }
1700
1701     // from ePS_DryRunning we can go to:
1702     //   - ePS_Stopped if something went wrong during DryRunning
1703     //   - ePS_WaitingForStreamEnable if there is a requested to enable
1704     if (m_state == ePS_DryRunning) {
1705         if((next_state != ePS_Stopped) &&
1706            (next_state != ePS_WaitingForStreamEnable)) {
1707             goto updateState_exit_with_error;
1708         }
1709         if (next_state == ePS_Stopped) {
1710             result = doStop();
1711         } else {
1712             result = doWaitForStreamEnable();
1713         }
1714         if (result) {return true;}
1715         else goto updateState_exit_change_failed;
1716     }
1717
1718     // from ePS_WaitingForStreamEnable we can go to:
1719     //   - ePS_DryRunning if something went wrong while waiting
1720     //   - ePS_Running if the stream enabled correctly
1721     if (m_state == ePS_WaitingForStreamEnable) {
1722         if((next_state != ePS_DryRunning) &&
1723            (next_state != ePS_Running)) {
1724             goto updateState_exit_with_error;
1725         }
1726         if (next_state == ePS_DryRunning) {
1727             result = doDryRunning();
1728         } else {
1729             result = doRunning();
1730         }
1731         if (result) {return true;}
1732         else goto updateState_exit_change_failed;
1733     }
1734
1735     // from ePS_Running we can only start waiting for a disabled stream
1736     if (m_state == ePS_Running) {
1737         if(next_state != ePS_WaitingForStreamDisable) {
1738             goto updateState_exit_with_error;
1739         }
1740         result = doWaitForStreamDisable();
1741         if (result) {return true;}
1742         else goto updateState_exit_change_failed;
1743     }
1744
1745     // from ePS_WaitingForStreamDisable we can go to DryRunning
1746     if (m_state == ePS_WaitingForStreamDisable) {
1747         if(next_state != ePS_DryRunning) {
1748             goto updateState_exit_with_error;
1749         }
1750         result = doDryRunning();
1751         if (result) {return true;}
1752         else goto updateState_exit_change_failed;
1753     }
1754
1755     // if we arrive here there is an error
1756 updateState_exit_with_error:
1757     debugError("Invalid state transition: %s => %s\n",
1758         ePSToString(m_state), ePSToString(next_state));
1759     SIGNAL_ACTIVITY_ALL;
1760     return false;
1761 updateState_exit_change_failed:
1762     debugError("State transition failed: %s => %s\n",
1763         ePSToString(m_state), ePSToString(next_state));
1764     SIGNAL_ACTIVITY_ALL;
1765     return false;
1766 }
1767
1768 bool StreamProcessor::canProducePacket()
1769 {
1770     return canProduce(getNominalFramesPerPacket());
1771 }
1772 bool StreamProcessor::canProducePeriod()
1773 {
1774     return canProduce(m_StreamProcessorManager.getPeriodSize());
1775 }
1776 bool StreamProcessor::canProduce(unsigned int nframes)
1777 {
1778     if(m_in_xrun) return true;
1779     if(m_state == ePS_Running && m_next_state == ePS_Running) {
1780         // can we put a certain amount of frames into the buffer?
1781         unsigned int bufferspace = m_data_buffer->getBufferSpace();
1782         if(bufferspace >= nframes) {
1783             return true;
1784         } else return false;
1785     } else {
1786         if(getType() == ePT_Transmit) {
1787             // if we are an xmit SP, we cannot accept frames
1788             // when not running
1789             return false;
1790         } else {
1791             // if we are a receive SP, we can always accept frames
1792             // when not running
1793             return true;
1794         }
1795     }
1796 }
1797
1798 bool StreamProcessor::canConsumePacket()
1799 {
1800     return canConsume(getNominalFramesPerPacket());
1801 }
1802 bool StreamProcessor::canConsumePeriod()
1803 {
1804     return canConsume(m_StreamProcessorManager.getPeriodSize());
1805 }
1806 bool StreamProcessor::canConsume(unsigned int nframes)
1807 {
1808     if(m_in_xrun) return true;
1809     if(m_state == ePS_Running && m_next_state == ePS_Running) {
1810         // check whether we already fullfil the criterion
1811         unsigned int bufferfill = m_data_buffer->getBufferFill();
1812         if(bufferfill >= nframes) {
1813             return true;
1814         } else return false;
1815     } else {
1816         if(getType() == ePT_Transmit) {
1817             // if we are an xmit SP, and we're not running,
1818             // we can always provide frames
1819             return true;
1820         } else {
1821             // if we are a receive SP, we can't provide frames
1822             // when not running
1823             return false;
1824         }
1825     }
1826 }
1827
1828 /***********************************************
1829  * Helper routines                             *
1830  ***********************************************/
1831 // FIXME: I think this can be removed and replaced by putSilenceFrames
1832 bool
1833 StreamProcessor::transferSilence(unsigned int nframes)
1834 {
1835     bool retval;
1836
1837     #ifdef DEBUG
1838     signed int fc;
1839     ffado_timestamp_t ts_tail_tmp;
1840     m_data_buffer->getBufferTailTimestamp(&ts_tail_tmp, &fc);
1841     if (fc != 0) {
1842         debugWarning("Prefilling a buffer that already contains %d frames\n", fc);
1843     }
1844     #endif
1845
1846     // prepare a buffer of silence
1847     char *dummybuffer = (char *)calloc(getEventSize(), nframes * getEventsPerFrame());
1848     transmitSilenceBlock(dummybuffer, nframes, 0);
1849
1850     // add the silence data to the ringbuffer
1851     if(m_data_buffer->preloadFrames(nframes, dummybuffer, true)) {
1852         retval = true;
1853     } else {
1854         debugWarning("Could not write to event buffer\n");
1855         retval = false;
1856     }
1857
1858     free(dummybuffer);
1859     return retval;
1860 }
1861
1862 /**
1863  * @brief convert a eProcessorState to a string
1864  * @param s the state
1865  * @return a char * describing the state
1866  */
1867 const char *
1868 StreamProcessor::ePSToString(enum eProcessorState s) {
1869     switch (s) {
1870         case ePS_Invalid: return "ePS_Invalid";
1871         case ePS_Created: return "ePS_Created";
1872         case ePS_Stopped: return "ePS_Stopped";
1873         case ePS_WaitingForStream: return "ePS_WaitingForStream";
1874         case ePS_DryRunning: return "ePS_DryRunning";
1875         case ePS_WaitingForStreamEnable: return "ePS_WaitingForStreamEnable";
1876         case ePS_Running: return "ePS_Running";
1877         case ePS_WaitingForStreamDisable: return "ePS_WaitingForStreamDisable";
1878         case ePS_Error: return "ePS_Error";
1879         default: return "error: unknown state";
1880     }
1881 }
1882
1883 /**
1884  * @brief convert a eProcessorType to a string
1885  * @param t the type
1886  * @return a char * describing the state
1887  */
1888 const char *
1889 StreamProcessor::ePTToString(enum eProcessorType t) {
1890     switch (t) {
1891         case ePT_Receive: return "Receive";
1892         case ePT_Transmit: return "Transmit";
1893         default: return "error: unknown type";
1894     }
1895 }
1896
1897 /***********************************************
1898  * Debug                                       *
1899  ***********************************************/
1900 void
1901 StreamProcessor::dumpInfo()
1902 {
1903     #ifdef DEBUG
1904     debugOutputShort( DEBUG_LEVEL_NORMAL, " StreamProcessor %p, %s:\n", this, ePTToString(m_processor_type));
1905     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel    : %d, %d\n", m_1394service.getPort(), m_channel);
1906     IsoHandler *h = m_IsoHandlerManager.getHandlerForStream(this);
1907     if (h) {
1908         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packets, Dropped, Skipped : %d, %d, %d\n",
1909                                               h->m_packets, h->m_dropped, h->m_skipped);
1910     } else {
1911         debugError("No handler for stream??\n");
1912     }
1913     uint64_t now = m_1394service.getCycleTimerTicks();
1914     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Now                   : %011llu (%03us %04uc %04ut)\n",
1915                         now,
1916                         (unsigned int)TICKS_TO_SECS(now),
1917                         (unsigned int)TICKS_TO_CYCLES(now),
1918                         (unsigned int)TICKS_TO_OFFSET(now));
1919     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Xrun?                 : %s\n", (m_in_xrun ? "True":"False"));
1920     if (m_state == m_next_state) {
1921         debugOutputShort( DEBUG_LEVEL_NORMAL, "  State                 : %s\n",
1922                                             ePSToString(m_state));
1923     } else {
1924         debugOutputShort( DEBUG_LEVEL_NORMAL, "  State                 : %s (Next: %s)\n",
1925                                               ePSToString(m_state), ePSToString(m_next_state));
1926         debugOutputShort( DEBUG_LEVEL_NORMAL, "    transition at       : %u\n", m_cycle_to_switch_state);
1927     }
1928     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer                : %p\n", m_data_buffer);
1929     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Framerate             : Nominal: %u, Sync: %f, Buffer %f\n",
1930                                           m_StreamProcessorManager.getNominalRate(),
1931                                           24576000.0/m_StreamProcessorManager.getSyncSource().m_data_buffer->getRate(),
1932                                           24576000.0/m_data_buffer->getRate());
1933     float d = getSyncDelay();
1934     debugOutputShort(DEBUG_LEVEL_NORMAL, "  Sync delay             : %f ticks (%f frames, %f cy)\n",
1935                                          d, d/getTicksPerFrame(),
1936                                          d/((float)TICKS_PER_CYCLE));
1937     #endif
1938     m_data_buffer->dumpInfo();
1939 }
1940
1941 void
1942 StreamProcessor::printBufferInfo()
1943 {
1944     debugOutput(DEBUG_LEVEL_NORMAL,
1945                 "(%p, %8s) fc: %d fill: %u\n",
1946                 this, getTypeString(), m_data_buffer->getFrameCounter(), m_data_buffer->getBufferFill() );
1947 }
1948
1949 void
1950 StreamProcessor::setVerboseLevel(int l) {
1951     setDebugLevel(l);
1952     PortManager::setVerboseLevel(l);
1953     m_data_buffer->setVerboseLevel(l);
1954     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1955 }
1956
1957 } // end of namespace
Note: See TracBrowser for help on using the browser.