root/branches/api-cleanup/src/libstreaming/generic/StreamProcessor.cpp

Revision 821, 67.5 kB (checked in by ppalmers, 16 years ago)

make xrun hanling more robust

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