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

Revision 864, 19.0 kB (checked in by ppalmers, 16 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

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