root/branches/ppalmers-streaming/src/libstreaming/generic/StreamProcessor.h

Revision 719, 12.3 kB (checked in by ppalmers, 16 years ago)

backup commit

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 library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #ifndef __FFADO_STREAMPROCESSOR__
25 #define __FFADO_STREAMPROCESSOR__
26
27 #include "IsoStream.h"
28 #include "PortManager.h"
29
30 #include "libutil/StreamStatistics.h"
31 #include "libutil/TimestampedBuffer.h"
32 #include "libutil/OptionContainer.h"
33
34 #include "debugmodule/debugmodule.h"
35
36 #include <pthread.h>
37
38 namespace Streaming {
39
40     class StreamProcessorManager;
41 /*!
42 \brief Class providing a generic interface for Stream Processors
43
44  A stream processor multiplexes or demultiplexes an ISO stream into a
45  collection of ports. This class should be subclassed, and the relevant
46  functions should be overloaded.
47
48 */
49 class StreamProcessor : public IsoStream,
50                         public PortManager,
51                         public Util::TimestampedBufferClient,
52                         public Util::OptionContainer
53 {
54
55     friend class StreamProcessorManager; // FIXME: get rid of this
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 scheduleAndWaitForStateTransition(enum eProcessorState state,
106                                            uint64_t time_instant,
107                                            enum eProcessorState wait_state);
108 public:
109     bool isRunning()
110             {return m_state == ePS_Running;};
111     bool isDryRunning()
112             {return m_state == ePS_DryRunning;};
113
114 //--- state stuff (TODO: cleanup)
115     bool startDryRunning(int64_t time_to_start_at);
116     bool startRunning(int64_t time_to_start_at);
117     bool stopDryRunning(int64_t time_to_stop_at);
118     bool stopRunning(int64_t time_to_stop_at);
119
120     // the main difference between init and prepare is that when prepare is called,
121     // the SP is registered to a manager (FIXME: can't it be called by the manager?)
122     bool init();
123     bool prepare();
124     ///> stop the SP from running or dryrunning
125     bool stop();
126 // constructor/destructor
127 public:
128     StreamProcessor(enum eProcessorType type, int port);
129     virtual ~StreamProcessor();
130
131 // the receive/transmit functions
132 public:
133     // the transmit interface accepts frames and provides packets
134     // implement these for a transmit SP
135     // leave default for a receive SP
136     virtual enum raw1394_iso_disposition
137     getPacket(unsigned char *data, unsigned int *length,
138                 unsigned char *tag, unsigned char *sy,
139                 int cycle, unsigned int dropped, unsigned int max_length)
140         {debugWarning("call not allowed\n"); return RAW1394_ISO_STOP;};
141     virtual bool putFrames(unsigned int nbframes, int64_t ts)
142         {debugWarning("call not allowed\n"); return false;};
143     virtual bool putFramesDry(unsigned int nbframes, int64_t ts)
144         {debugWarning("call not allowed\n"); return false;};
145     virtual bool processWriteBlock(char *data, unsigned int nevents, unsigned int offset)
146         {debugWarning("call not allowed\n"); return false;};
147
148     // the receive interface accepts packets and provides frames
149    
150     // the following two methods are to be implemented by subclasses
151     virtual bool processPacketHeader(unsigned char *data, unsigned int length,
152                   unsigned char channel, unsigned char tag, unsigned char sy,
153                   unsigned int cycle, unsigned int dropped)
154         {debugWarning("call not allowed\n"); return false;};
155     virtual bool processPacketData(unsigned char *data, unsigned int length,
156                   unsigned char channel, unsigned char tag, unsigned char sy,
157                   unsigned int cycle, unsigned int dropped)
158         {debugWarning("call not allowed\n"); return false;};
159
160     // this one is implemented by us
161     enum raw1394_iso_disposition
162         putPacket(unsigned char *data, unsigned int length,
163                   unsigned char channel, unsigned char tag, unsigned char sy,
164                   unsigned int cycle, unsigned int dropped);
165
166     bool getFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents to the client
167 protected:
168     // to be implemented by the children
169     virtual bool processReadBlock(char *data, unsigned int nevents, unsigned int offset)
170         {debugWarning("call not allowed\n"); return false;};
171     virtual bool provideSilenceBlock(unsigned int nevents, unsigned int offset)
172         {debugWarning("call not allowed\n"); return false;};
173
174 private:
175     bool getFramesDry(unsigned int nbframes, int64_t ts);
176     bool getFramesWet(unsigned int nbframes, int64_t ts);
177
178     // move to private?
179     bool xrunOccurred() { return (m_xruns>0); }; // FIXME: m_xruns not updated
180
181 protected: // FIXME: move to private
182     uint64_t m_dropped; /// FIXME:debug
183     uint64_t m_last_dropped; /// FIXME:debug
184     int m_last_good_cycle; /// FIXME:debug
185     uint64_t m_last_timestamp; /// last timestamp (in ticks)
186     uint64_t m_last_timestamp2; /// last timestamp (in ticks)
187     uint64_t m_last_timestamp_at_period_ticks;
188
189 //--- data buffering and accounting
190 public: // FIXME: should be private
191     Util::TimestampedBuffer *m_data_buffer;
192
193 protected:
194     unsigned int m_xruns;
195
196     StreamProcessorManager *m_manager;
197
198     // frame counter & sync stuff
199     public:
200         /**
201          * @brief Can this StreamProcessor handle a transfer of nframes frames?
202          *
203          * this function indicates if the streamprocessor can handle a transfer of
204          * nframes frames. It is used to detect underruns-to-be.
205          *
206          * @param nframes number of frames
207          * @return true if the StreamProcessor can handle this amount of frames
208          *         false if it can't
209          */
210         bool canClientTransferFrames(unsigned int nframes);
211
212         /**
213          * @brief drop nframes from the internal buffer
214          *
215          * this function drops nframes from the internal buffers, without any
216          * specification on what frames are dropped. Timestamps are not updated.
217          *
218          * @param nframes number of frames
219          * @return true if the operation was successful
220          */
221         bool dropFrames(unsigned int nframes);
222
223         /**
224          * \brief return the time until the next period boundary should be signaled (in microseconds)
225          *
226          * Return the time until the next period boundary signal. If this StreamProcessor
227          * is the current synchronization source, this function is called to
228          * determine when a buffer transfer can be made. When this value is
229          * smaller than 0, a period boundary is assumed to be crossed, hence a
230          * transfer can be made.
231          *
232          * \return the time in usecs
233          */
234         int64_t getTimeUntilNextPeriodSignalUsecs();
235         /**
236          * \brief return the time of the next period boundary (in microseconds)
237          *
238          * Returns the time of the next period boundary, in microseconds. The
239          * goal of this function is to determine the exact point of the period
240          * boundary. This is assumed to be the point at which the buffer transfer should
241          * take place, meaning that it can be used as a reference timestamp for transmitting
242          * StreamProcessors
243          *
244          * \return the time in usecs
245          */
246         uint64_t getTimeAtPeriodUsecs();
247
248         /**
249          * \brief return the time of the next period boundary (in internal units)
250          *
251          * The same as getTimeAtPeriodUsecs() but in internal units.
252          *
253          * @return the time in internal units
254          */
255         uint64_t getTimeAtPeriod();
256
257         uint64_t getTimeNow();
258
259
260         /**
261          * Returns the sync delay. This is the time a syncsource
262          * delays a period signal, e.g. to cope with buffering.
263          * @return the sync delay
264          */
265         int getSyncDelay() {return m_sync_delay;};
266         /**
267          * sets the sync delay
268          * @param d sync delay
269          */
270         void setSyncDelay(int d) {m_sync_delay = d;};
271
272         /**
273          * @brief get the maximal frame latency
274          *
275          * The maximum frame latency is the maximum time that will elapse
276          * between the frame being received by the 1394 stack, and the moment this
277          * frame is presented to the StreamProcessor.
278          *
279          * For transmit SP's this is the maximum time that a frame is requested by
280          * the handler ahead of the time the frame is intended to be transmitted.
281          *
282          * This is useful to figure out how longer than the actual reception time
283          * we have to wait before trying to read the frame from the SP.
284          *
285          * @return maximal frame latency
286          */
287         int getMaxFrameLatency();
288
289         float getTicksPerFrame();
290
291         int getLastCycle() {return m_last_cycle;};
292
293         int getBufferFill();
294
295         // Child implementation interface
296         /**
297         * @brief prepare the child SP
298         * @return true if successful, false otherwise
299         * @pre the m_manager pointer points to a valid manager
300         * @post getEventsPerFrame() returns the correct value
301         * @post getEventSize() returns the correct value
302         * @post getUpdatePeriod() returns the correct value
303         * @post processPacketHeader(...) can be called
304         * @post processPacketData(...) can be called
305         */
306         virtual bool prepareChild() = 0;
307         /**
308          * @brief get the number of events contained in one frame
309          * @return the number of events contained in one frame
310          */
311         virtual unsigned int getEventsPerFrame() = 0;
312
313         /**
314          * @brief get the size of one frame in bytes
315          * @return the size of one frame in bytes
316          */
317         virtual unsigned int getEventSize() = 0;
318
319         /**
320          * @brief get the nominal number of frames between buffer updates
321          * @return the nominal number of frames between buffer updates
322          */
323         virtual unsigned int getUpdatePeriod() = 0;
324
325     protected:
326         float m_ticks_per_frame;
327         int m_last_cycle;
328         int m_sync_delay;
329
330 protected: // SPM related
331     void setManager(StreamProcessorManager *manager) {m_manager=manager;};
332     void clearManager() {m_manager=NULL;};
333
334 public:
335     // debug stuff
336     virtual void dumpInfo();
337     virtual void setVerboseLevel(int l);
338     StreamStatistics m_PacketStat;
339     StreamStatistics m_PeriodStat;
340     StreamStatistics m_WakeupStat;
341     DECLARE_DEBUG_MODULE;
342
343 };
344
345 }
346
347 #endif /* __FFADO_STREAMPROCESSOR__ */
348
349
Note: See TracBrowser for help on using the browser.