root/trunk/libffado/src/libstreaming/generic/StreamProcessor.h

Revision 857, 20.0 kB (checked in by ppalmers, 13 years ago)

Introduce distinction between empty and silent packets. When shutting down a transmit SP, we now send silent (= valid, but all audio muted) packets instead of empty (w/o
payload) packets for a while. This should solve the shutdown issue with the motu's.

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 #ifndef __FFADO_STREAMPROCESSOR__
25 #define __FFADO_STREAMPROCESSOR__
26
27 #include "ffadodevice.h"
28
29 #include "PortManager.h"
30
31 #include "libutil/StreamStatistics.h"
32 #include "libutil/TimestampedBuffer.h"
33 #include "libutil/OptionContainer.h"
34
35 #include "debugmodule/debugmodule.h"
36 #include <semaphore.h>
37
38 class Ieee1394Service;
39 class IsoHandlerManager;
40
41 namespace Streaming {
42
43     class StreamProcessorManager;
44 /*!
45 \brief Class providing a generic interface for Stream Processors
46
47  A stream processor multiplexes or demultiplexes an ISO stream into a
48  collection of ports. This class should be subclassed, and the relevant
49  functions should be overloaded.
50
51 */
52 class StreamProcessor : public PortManager,
53                         public Util::TimestampedBufferClient,
54                         public Util::OptionContainer
55 {
56 public:
57     ///> the streamprocessor type
58     enum eProcessorType {
59         ePT_Receive,
60         ePT_Transmit
61     };
62     ///> returns the type of the streamprocessor
63     virtual enum eProcessorType getType() { return m_processor_type; };
64 private:
65     // this can only be set by the constructor
66     enum eProcessorType m_processor_type;
67     // pretty printing
68     const char *ePTToString(enum eProcessorType);
69 protected:
70     ///> the state the streamprocessor is in
71     enum eProcessorState {
72         ePS_Invalid,
73         ePS_Created,
74         // ePS_WaitingToStop, FIXME: this will be needed for the MOTU's
75         ePS_Stopped,
76         ePS_WaitingForStream,
77         ePS_DryRunning,
78         ePS_WaitingForStreamEnable,
79         ePS_Running,
80         ePS_WaitingForStreamDisable,
81     };
82
83     ///> set the SP state to a specific value
84     void setState(enum eProcessorState);
85     ///> get the SP state
86     enum eProcessorState getState() {return m_state;};
87 private:
88     enum eProcessorState m_state;
89     // state switching
90     enum eProcessorState m_next_state;
91     unsigned int m_cycle_to_switch_state;
92     bool updateState();
93     // pretty printing
94     const char *ePSToString(enum eProcessorState);
95
96     bool doStop();
97     bool doWaitForRunningStream();
98     bool doDryRunning();
99     bool doWaitForStreamEnable();
100     bool doRunning();
101     bool doWaitForStreamDisable();
102
103     bool scheduleStateTransition(enum eProcessorState state, uint64_t time_instant);
104     bool waitForState(enum eProcessorState state, unsigned int timeout);
105
106 public: //--- state stuff
107     bool isRunning()
108             {return m_state == ePS_Running;};
109     bool isDryRunning()
110             {return m_state == ePS_DryRunning;};
111     bool isStopped()
112             {return m_state == ePS_Stopped;};
113     bool isWaitingForStream()
114             {return m_state == ePS_WaitingForStream;};
115
116     // these schedule and wait for the state transition
117     bool startDryRunning(int64_t time_to_start_at);
118     bool startRunning(int64_t time_to_start_at);
119     bool stopDryRunning(int64_t time_to_stop_at);
120     bool stopRunning(int64_t time_to_stop_at);
121
122     // these only schedule the transition
123     bool scheduleStartDryRunning(int64_t time_to_start_at);
124     bool scheduleStartRunning(int64_t time_to_start_at);
125     bool scheduleStopDryRunning(int64_t time_to_stop_at);
126     bool scheduleStopRunning(int64_t time_to_stop_at);
127
128     // the main difference between init and prepare is that when prepare is called,
129     // the SP is registered to a manager (FIXME: can't it be called by the manager?)
130     bool init();
131     bool prepare();
132
133 public: // constructor/destructor
134     StreamProcessor(FFADODevice &parent, enum eProcessorType type);
135     virtual ~StreamProcessor();
136 protected:
137     FFADODevice&                m_Parent;
138     Ieee1394Service&            m_1394service;
139     IsoHandlerManager&          m_IsoHandlerManager;
140     StreamProcessorManager&     m_StreamProcessorManager;
141     unsigned int                m_local_node_id;
142
143 public: // the public receive/transmit functions
144     // the transmit interface accepts frames and provides packets
145     // implement these for a transmit SP
146     // leave default for a receive SP
147
148     // the receive interface accepts packets and provides frames
149     // these are implemented by the parent SP
150     enum raw1394_iso_disposition
151         putPacket(unsigned char *data, unsigned int length,
152                   unsigned char channel, unsigned char tag, unsigned char sy,
153                   unsigned int cycle, unsigned int dropped);
154
155     enum raw1394_iso_disposition
156     getPacket(unsigned char *data, unsigned int *length,
157                 unsigned char *tag, unsigned char *sy,
158                 int cycle, unsigned int dropped, unsigned int max_length);
159
160     bool getFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents to the client
161     bool putFrames(unsigned int nbframes, int64_t ts); ///< transfer the client contents to the buffer
162
163     unsigned int getSignalPeriod() {return m_signal_period;};
164     bool setSignalPeriod(unsigned int p) {m_signal_period=p; return true;};
165     /**
166      * @brief waits for a 'signal' (blocking)
167      *
168      * a 'signal' is:
169      * when type==Receive:
170      *  - one signal_period of frames is present in the buffer
171      *    (received by the iso side)
172      *  - an error has occurred (xrun, iso error, ...)
173      * when type==Transmit:
174      *  - at least one signal_period of frames are present in the buffer
175      *    (have been written into it by the client)
176      *  - an error occurred
177      *
178      * @return true if the 'signal' is available, false if error
179      */
180     bool waitForSignal();
181
182     /**
183      * @brief checks for a 'signal' (non-blocking)
184      *
185      * a 'signal' is:
186      * when type==Receive:
187      *  - one signal_period of frames is present in the buffer
188      *    (received by the iso side)
189      *  - an error has occurred (xrun, iso error, ...)
190      * when type==Transmit:
191      *  - at least one signal_period of frames are present in the buffer
192      *    (have been written into it by the client)
193      *  - an error occurred
194      *
195      * @return true if the 'signal' is available, false if not (or error)
196      */
197     bool tryWaitForSignal();
198
199     /**
200      * @brief can a SP process (queue, dequeue) packets at this moment?
201      *
202      *
203      * @return true if packet processing makes sense
204      */
205     bool canProcessPackets();
206
207     /**
208      * @brief drop nframes from the internal buffer as if they were transferred to the client side
209      *
210      * Gets nframes of frames from the buffer as done by getFrames(), but does not transfer them
211      * to the client side. Instead they are discarded.
212      *
213      * @param nframes number of frames
214      * @return true if the operation was successful
215      */
216     bool dropFrames(unsigned int nframes, int64_t ts);
217
218     /**
219      * @brief put silence frames into the internal buffer
220      *
221      * Puts nframes of frames into the buffer as done by putFrames(), but does not transfer them
222      * from the client side. Instead, silent frames are used.
223      *
224      * @param nframes number of frames
225      * @return true if the operation was successful
226      */
227     bool putSilenceFrames(unsigned int nbframes, int64_t ts);
228
229     /**
230      * @brief Shifts the stream with the specified number of frames
231      *
232      * Used to align several streams to each other. It comes down to
233      * making sure the head timestamp corresponds to the timestamp of
234      * one master stream
235      *
236      * @param nframes the number of frames to shift
237      * @return true if successful
238      */
239     bool shiftStream(int nframes);
240
241     /**
242      * @brief tries to fill/sink the stream as far as possible
243      */
244     void flush();
245
246 protected: // the helper receive/transmit functions
247     enum eChildReturnValue {
248         eCRV_OK,
249         eCRV_Invalid,
250         eCRV_Packet,
251         eCRV_EmptyPacket,
252         eCRV_XRun,
253         eCRV_Again,
254         eCRV_Defer,
255     };
256     // to be implemented by the children
257     // the following methods are to be implemented by receive SP subclasses
258     virtual enum eChildReturnValue processPacketHeader(unsigned char *data, unsigned int length,
259                                      unsigned char channel, unsigned char tag,
260                                      unsigned char sy, unsigned int cycle,
261                                      unsigned int dropped)
262         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
263     virtual enum eChildReturnValue processPacketData(unsigned char *data, unsigned int length,
264                                    unsigned char channel, unsigned char tag,
265                                    unsigned char sy, unsigned int cycle,
266                                    unsigned int dropped)
267         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
268     virtual bool processReadBlock(char *data, unsigned int nevents, unsigned int offset)
269         {debugWarning("call not allowed\n"); return false;};
270
271     // the following methods are to be implemented by transmit SP subclasses
272     virtual enum eChildReturnValue generatePacketHeader(unsigned char *data, unsigned int *length,
273                                       unsigned char *tag, unsigned char *sy,
274                                       int cycle, unsigned int dropped,
275                                       unsigned int max_length)
276         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
277     virtual enum eChildReturnValue generatePacketData(unsigned char *data, unsigned int *length,
278                                     unsigned char *tag, unsigned char *sy,
279                                     int cycle, unsigned int dropped,
280                                     unsigned int max_length)
281         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
282     virtual enum eChildReturnValue generateEmptyPacketHeader(unsigned char *data, unsigned int *length,
283                                             unsigned char *tag, unsigned char *sy,
284                                             int cycle, unsigned int dropped,
285                                             unsigned int max_length)
286         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
287     virtual enum eChildReturnValue generateEmptyPacketData(unsigned char *data, unsigned int *length,
288                                           unsigned char *tag, unsigned char *sy,
289                                           int cycle, unsigned int dropped,
290                                           unsigned int max_length)
291         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
292     virtual enum eChildReturnValue generateSilentPacketHeader(unsigned char *data, unsigned int *length,
293                                             unsigned char *tag, unsigned char *sy,
294                                             int cycle, unsigned int dropped,
295                                             unsigned int max_length)
296         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
297     virtual enum eChildReturnValue generateSilentPacketData(unsigned char *data, unsigned int *length,
298                                           unsigned char *tag, unsigned char *sy,
299                                           int cycle, unsigned int dropped,
300                                           unsigned int max_length)
301         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
302     virtual bool processWriteBlock(char *data, unsigned int nevents, unsigned int offset)
303         {debugWarning("call not allowed\n"); return false;};
304     virtual bool transmitSilenceBlock(char *data, unsigned int nevents, unsigned int offset)
305         {debugWarning("call not allowed\n"); return false;};
306 protected: // some generic helpers
307     int provideSilenceToPort(Port *p, unsigned int offset, unsigned int nevents);
308     bool provideSilenceBlock(unsigned int nevents, unsigned int offset);
309
310 private:
311     bool getFramesDry(unsigned int nbframes, int64_t ts);
312     bool getFramesWet(unsigned int nbframes, int64_t ts);
313     bool putFramesDry(unsigned int nbframes, int64_t ts);
314     bool putFramesWet(unsigned int nbframes, int64_t ts);
315
316     bool transferSilence(unsigned int size);
317
318 public:
319     // move to private?
320     bool xrunOccurred() { return m_in_xrun; };
321
322 // the ISO interface (can we get rid of this?)
323 public:
324     int getChannel() {return m_channel;};
325     bool setChannel(int c)
326         {m_channel = c; return true;};
327
328     virtual unsigned int getNbPacketsIsoXmitBuffer();
329     virtual unsigned int getPacketsPerPeriod();
330     virtual unsigned int getMaxPacketSize() = 0;
331 private:
332     int m_channel;
333
334 protected: // FIXME: move to private
335     uint64_t m_dropped; /// FIXME:debug
336     uint64_t m_last_dropped; /// FIXME:debug
337     int m_last_good_cycle; /// FIXME:debug
338     uint64_t m_last_timestamp; /// last timestamp (in ticks)
339     uint64_t m_last_timestamp2; /// last timestamp (in ticks)
340     bool m_correct_last_timestamp;
341     uint64_t m_last_timestamp_at_period_ticks; // FIXME: still used?
342
343 //--- data buffering and accounting
344 public:
345     void getBufferHeadTimestamp ( ffado_timestamp_t *ts, signed int *fc )
346         {m_data_buffer->getBufferHeadTimestamp(ts, fc);};
347     void getBufferTailTimestamp ( ffado_timestamp_t *ts, signed int *fc )
348         {m_data_buffer->getBufferTailTimestamp(ts, fc);};
349
350     void setBufferTailTimestamp ( ffado_timestamp_t new_timestamp )
351         {m_data_buffer->setBufferTailTimestamp(new_timestamp);};
352     void setBufferHeadTimestamp ( ffado_timestamp_t new_timestamp )
353         {m_data_buffer->setBufferHeadTimestamp(new_timestamp);};
354 protected:
355     Util::TimestampedBuffer *m_data_buffer;
356     // the scratch buffer is temporary buffer space that can be
357     // used by any function. It's pre-allocated when the SP is created.
358     // the purpose is to avoid allocation of memory (or heap/stack) in
359     // an RT context
360     byte_t*         m_scratch_buffer;
361     size_t          m_scratch_buffer_size_bytes;
362
363 protected:
364     // frame counter & sync stuff
365     public:
366         /**
367          * @brief Can this StreamProcessor handle a transfer of nframes frames?
368          *
369          * this function indicates if the streamprocessor can handle a transfer of
370          * nframes frames. It is used to detect underruns-to-be.
371          *
372          * @param nframes number of frames
373          * @return true if the StreamProcessor can handle this amount of frames
374          *         false if it can't
375          */
376         bool canClientTransferFrames(unsigned int nframes);
377
378         /**
379          * \brief return the time until the next period boundary should be signaled (in microseconds)
380          *
381          * Return the time until the next period boundary signal. If this StreamProcessor
382          * is the current synchronization source, this function is called to
383          * determine when a buffer transfer can be made. When this value is
384          * smaller than 0, a period boundary is assumed to be crossed, hence a
385          * transfer can be made.
386          *
387          * \return the time in usecs
388          */
389         int64_t getTimeUntilNextPeriodSignalUsecs();
390         /**
391          * \brief return the time of the next period boundary (in microseconds)
392          *
393          * Returns the time of the next period boundary, in microseconds. The
394          * goal of this function is to determine the exact point of the period
395          * boundary. This is assumed to be the point at which the buffer transfer should
396          * take place, meaning that it can be used as a reference timestamp for transmitting
397          * StreamProcessors
398          *
399          * \return the time in usecs
400          */
401         uint64_t getTimeAtPeriodUsecs();
402
403         /**
404          * \brief return the time of the next period boundary (in internal units)
405          *
406          * The same as getTimeAtPeriodUsecs() but in internal units.
407          *
408          * @return the time in internal units
409          */
410         uint64_t getTimeAtPeriod();
411
412         uint64_t getTimeNow(); // FIXME: should disappear
413
414
415         /**
416          * Returns the sync delay. This is the time a syncsource
417          * delays a period signal, e.g. to cope with buffering.
418          * @return the sync delay
419          */
420         unsigned int getSyncDelay() {return m_sync_delay;};
421         /**
422          * sets the sync delay
423          * @param d sync delay
424          */
425         void setSyncDelay(unsigned int d);
426
427         /**
428          * @brief get the maximal frame latency
429          *
430          * The maximum frame latency is the maximum time that will elapse
431          * between the frame being received by the 1394 stack, and the moment this
432          * frame is presented to the StreamProcessor.
433          *
434          * For transmit SP's this is the maximum time that a frame is requested by
435          * the handler ahead of the time the frame is intended to be transmitted.
436          *
437          * This is useful to figure out how longer than the actual reception time
438          * we have to wait before trying to read the frame from the SP.
439          *
440          * @return maximal frame latency
441          */
442         int getMaxFrameLatency();
443
444         float getTicksPerFrame();
445
446         int getLastCycle() {return m_last_cycle;};
447
448         int getBufferFill();
449
450         // Child implementation interface
451         /**
452         * @brief prepare the child SP
453         * @return true if successful, false otherwise
454         * @pre the m_manager pointer points to a valid manager
455         * @post getEventsPerFrame() returns the correct value
456         * @post getEventSize() returns the correct value
457         * @post getUpdatePeriod() returns the correct value
458         * @post processPacketHeader(...) can be called
459         * @post processPacketData(...) can be called
460         */
461         virtual bool prepareChild() = 0;
462         /**
463          * @brief get the number of events contained in one frame
464          * @return the number of events contained in one frame
465          */
466         virtual unsigned int getEventsPerFrame() = 0;
467
468         /**
469          * @brief get the size of one frame in bytes
470          * @return the size of one frame in bytes
471          */
472         virtual unsigned int getEventSize() = 0;
473
474         /**
475          * @brief get the nominal number of frames in a packet
476          *
477          * This is the amount of frames that is nominally present
478          * in one packet. It is recommended that in the receive handler
479          * you write this amount of frames when a valid packet has
480          * been received. (although this is not mandatory)
481          *
482          * @return the nominal number of frames in a packet
483          */
484         virtual unsigned int getNominalFramesPerPacket() = 0;
485
486         /**
487          * @brief get the nominal number of packets needed for a certain amount of frames
488          * @return the nominal number of packet necessary
489          */
490         virtual unsigned int getNominalPacketsNeeded(unsigned int nframes);
491
492         /**
493          * @brief returns the actual frame rate as calculated by the SP's DLL
494          * @return the actual frame rate as detected by the DLL
495          */
496         float getActualRate()
497             {return m_data_buffer->getRate();};
498
499     protected:
500         float m_ticks_per_frame;
501         int m_last_cycle;
502         unsigned int m_sync_delay;
503     private:
504         bool m_in_xrun;
505         sem_t m_signal_semaphore;
506         unsigned int m_signal_period;
507         unsigned int m_signal_offset;
508
509 public:
510     // debug stuff
511     virtual void dumpInfo();
512     virtual void setVerboseLevel(int l);
513     const char *getStateString()
514         {return ePSToString(getState());};
515     const char *getTypeString()
516         {return ePTToString(getType());};
517     StreamStatistics m_PacketStat;
518     StreamStatistics m_PeriodStat;
519     StreamStatistics m_WakeupStat;
520     DECLARE_DEBUG_MODULE;
521 };
522
523 }
524
525 #endif /* __FFADO_STREAMPROCESSOR__ */
526
527
Note: See TracBrowser for help on using the browser.