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

Revision 1190, 17.2 kB (checked in by ppalmers, 15 years ago)

remove unused code, clean up for release

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/TimestampedBuffer.h"
32 #include "libutil/OptionContainer.h"
33
34 #include "debugmodule/debugmodule.h"
35
36 #include <pthread.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_Stopped,
75         ePS_WaitingForStream,
76         ePS_DryRunning,
77         ePS_WaitingForStreamEnable,
78         ePS_Running,
79         ePS_WaitingForStreamDisable,
80     };
81
82     ///> set the SP state to a specific value
83     void setState(enum eProcessorState);
84     ///> get the SP state
85     enum eProcessorState getState() {return m_state;};
86 private:
87     enum eProcessorState m_state;
88     // state switching
89     enum eProcessorState m_next_state;
90     unsigned int m_cycle_to_switch_state;
91     bool updateState();
92     // pretty printing
93     const char *ePSToString(enum eProcessorState);
94
95     bool doStop();
96     bool doWaitForRunningStream();
97     bool doDryRunning();
98     bool doWaitForStreamEnable();
99     bool doRunning();
100     bool doWaitForStreamDisable();
101
102     bool scheduleStateTransition(enum eProcessorState state, uint64_t time_instant);
103     bool waitForState(enum eProcessorState state, unsigned int timeout);
104
105 public: //--- state stuff
106     bool isRunning()
107             {return m_state == ePS_Running;};
108     bool isDryRunning()
109             {return m_state == ePS_DryRunning;};
110     bool isStopped()
111             {return m_state == ePS_Stopped;};
112     bool isWaitingForStream()
113             {return m_state == ePS_WaitingForStream;};
114
115     // these schedule and wait for the state transition
116     bool startDryRunning(int64_t time_to_start_at);
117     bool startRunning(int64_t time_to_start_at);
118     bool stopDryRunning(int64_t time_to_stop_at);
119     bool stopRunning(int64_t time_to_stop_at);
120
121     // these only schedule the transition
122     bool scheduleStartDryRunning(int64_t time_to_start_at);
123     bool scheduleStartRunning(int64_t time_to_start_at);
124     bool scheduleStopDryRunning(int64_t time_to_stop_at);
125     bool scheduleStopRunning(int64_t time_to_stop_at);
126
127     // the main difference between init and prepare is that when prepare is called,
128     // the SP is registered to a manager (FIXME: can't it be called by the manager?)
129     bool init();
130     bool prepare();
131
132     void handleBusReset();
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                   uint32_t pkt_ctr, unsigned int dropped, unsigned int skipped);
155
156     enum raw1394_iso_disposition
157     getPacket(unsigned char *data, unsigned int *length,
158               unsigned char *tag, unsigned char *sy,
159               uint32_t pkt_ctr, unsigned int dropped,
160               unsigned int skipped, unsigned int max_length);
161
162     bool getFrames(unsigned int nbframes, int64_t ts); ///< transfer the buffer contents to the client
163     bool putFrames(unsigned int nbframes, int64_t ts); ///< transfer the client contents to the buffer
164
165     bool canProducePacket();
166     bool canProducePeriod();
167     bool canProduce(unsigned int nframes);
168
169     bool canConsumePacket();
170     bool canConsumePeriod();
171     bool canConsume(unsigned int nframes);
172
173 public:
174     /**
175      * @brief drop nframes from the internal buffer as if they were transferred to the client side
176      *
177      * Gets nframes of frames from the buffer as done by getFrames(), but does not transfer them
178      * to the client side. Instead they are discarded.
179      *
180      * @param nframes number of frames
181      * @return true if the operation was successful
182      */
183     bool dropFrames(unsigned int nframes, int64_t ts);
184
185     /**
186      * @brief put silence frames into the internal buffer
187      *
188      * Puts nframes of frames into the buffer as done by putFrames(), but does not transfer them
189      * from the client side. Instead, silent frames are used.
190      *
191      * @param nframes number of frames
192      * @return true if the operation was successful
193      */
194     bool putSilenceFrames(unsigned int nbframes, int64_t ts);
195
196     /**
197      * @brief Shifts the stream with the specified number of frames
198      *
199      * Used to align several streams to each other. It comes down to
200      * making sure the head timestamp corresponds to the timestamp of
201      * one master stream
202      *
203      * @param nframes the number of frames to shift
204      * @return true if successful
205      */
206     bool shiftStream(int nframes);
207
208     /**
209      * @brief tries to fill/sink the stream as far as possible
210      */
211     void flush();
212
213 protected: // the helper receive/transmit functions
214     enum eChildReturnValue {
215         eCRV_OK,
216         eCRV_Invalid,
217         eCRV_Packet,
218         eCRV_EmptyPacket,
219         eCRV_XRun,
220         eCRV_Again,
221         eCRV_Defer,
222     };
223     // to be implemented by the children
224     // the following methods are to be implemented by receive SP subclasses
225     virtual enum eChildReturnValue processPacketHeader(unsigned char *data, unsigned int length,
226                                                        unsigned char tag, unsigned char sy,
227                                                        uint32_t pkt_ctr)
228         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
229     virtual enum eChildReturnValue processPacketData(unsigned char *data, unsigned int length)
230         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
231     virtual bool processReadBlock(char *data, unsigned int nevents, unsigned int offset)
232         {debugWarning("call not allowed\n"); return false;};
233
234     // the following methods are to be implemented by transmit SP subclasses
235     virtual enum eChildReturnValue generatePacketHeader(unsigned char *data, unsigned int *length,
236                                                         unsigned char *tag, unsigned char *sy,
237                                                         uint32_t pkt_ctr)
238         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
239     virtual enum eChildReturnValue generatePacketData(unsigned char *data, unsigned int *length)
240         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
241     virtual enum eChildReturnValue generateEmptyPacketHeader(unsigned char *data, unsigned int *length,
242                                                              unsigned char *tag, unsigned char *sy,
243                                                              uint32_t pkt_ctr)
244         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
245     virtual enum eChildReturnValue generateEmptyPacketData(unsigned char *data, unsigned int *length)
246         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
247     virtual enum eChildReturnValue generateSilentPacketHeader(unsigned char *data, unsigned int *length,
248                                                               unsigned char *tag, unsigned char *sy,
249                                                               uint32_t pkt_ctr)
250         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
251     virtual enum eChildReturnValue generateSilentPacketData(unsigned char *data, unsigned int *length)
252         {debugWarning("call not allowed\n"); return eCRV_Invalid;};
253     virtual bool processWriteBlock(char *data, unsigned int nevents, unsigned int offset)
254         {debugWarning("call not allowed\n"); return false;};
255     virtual bool transmitSilenceBlock(char *data, unsigned int nevents, unsigned int offset)
256         {debugWarning("call not allowed\n"); return false;};
257 protected: // some generic helpers
258     int provideSilenceToPort(Port *p, unsigned int offset, unsigned int nevents);
259     bool provideSilenceBlock(unsigned int nevents, unsigned int offset);
260
261 private:
262     bool getFramesDry(unsigned int nbframes, int64_t ts);
263     bool getFramesWet(unsigned int nbframes, int64_t ts);
264     bool putFramesDry(unsigned int nbframes, int64_t ts);
265     bool putFramesWet(unsigned int nbframes, int64_t ts);
266
267     bool transferSilence(unsigned int size);
268
269 public:
270     // move to private?
271     bool xrunOccurred() { return m_in_xrun; };
272     void handlerDied();
273
274 // the ISO interface (can we get rid of this?)
275 public:
276     int getChannel() {return m_channel;};
277     bool setChannel(int c)
278         {m_channel = c; return true;};
279
280     virtual unsigned int getNbPacketsIsoXmitBuffer();
281     virtual unsigned int getPacketsPerPeriod();
282     virtual unsigned int getMaxPacketSize() = 0;
283 private:
284     int m_channel;
285
286 protected: // FIXME: move to private
287     uint64_t m_last_timestamp; /// last timestamp (in ticks)
288 private:
289     uint64_t m_last_timestamp2; /// last timestamp (in ticks)
290 protected:
291     bool m_correct_last_timestamp;
292     uint64_t m_last_timestamp_at_period_ticks; // FIXME: still used?
293
294 //--- data buffering and accounting
295 public:
296     void getBufferHeadTimestamp ( ffado_timestamp_t *ts, signed int *fc )
297         {m_data_buffer->getBufferHeadTimestamp(ts, fc);};
298     void getBufferTailTimestamp ( ffado_timestamp_t *ts, signed int *fc )
299         {m_data_buffer->getBufferTailTimestamp(ts, fc);};
300
301     void setBufferTailTimestamp ( ffado_timestamp_t new_timestamp )
302         {m_data_buffer->setBufferTailTimestamp(new_timestamp);};
303     void setBufferHeadTimestamp ( ffado_timestamp_t new_timestamp )
304         {m_data_buffer->setBufferHeadTimestamp(new_timestamp);};
305 protected:
306     Util::TimestampedBuffer *m_data_buffer;
307     // the scratch buffer is temporary buffer space that can be
308     // used by any function. It's pre-allocated when the SP is created.
309     // the purpose is to avoid allocation of memory (or heap/stack) in
310     // an RT context
311     byte_t*         m_scratch_buffer;
312     size_t          m_scratch_buffer_size_bytes;
313
314 protected:
315     // frame counter & sync stuff
316     public:
317         /**
318          * @brief Can this StreamProcessor handle a transfer of nframes frames?
319          *
320          * this function indicates if the streamprocessor can handle a transfer of
321          * nframes frames. It is used to detect underruns-to-be.
322          *
323          * @param nframes number of frames
324          * @return true if the StreamProcessor can handle this amount of frames
325          *         false if it can't
326          */
327         bool canClientTransferFrames(unsigned int nframes);
328
329         /**
330          * \brief return the time until the next period boundary should be signaled (in microseconds)
331          *
332          * Return the time until the next period boundary signal. If this StreamProcessor
333          * is the current synchronization source, this function is called to
334          * determine when a buffer transfer can be made. When this value is
335          * smaller than 0, a period boundary is assumed to be crossed, hence a
336          * transfer can be made.
337          *
338          * \return the time in usecs
339          */
340         int64_t getTimeUntilNextPeriodSignalUsecs();
341         /**
342          * \brief return the time of the next period boundary (in microseconds)
343          *
344          * Returns the time of the next period boundary, in microseconds. The
345          * goal of this function is to determine the exact point of the period
346          * boundary. This is assumed to be the point at which the buffer transfer should
347          * take place, meaning that it can be used as a reference timestamp for transmitting
348          * StreamProcessors
349          *
350          * \return the time in usecs
351          */
352         uint64_t getTimeAtPeriodUsecs();
353
354         /**
355          * \brief return the time of the next period boundary (in internal units)
356          *
357          * The same as getTimeAtPeriodUsecs() but in internal units.
358          *
359          * @return the time in internal units
360          */
361         uint64_t getTimeAtPeriod();
362
363         uint64_t getTimeNow(); // FIXME: should disappear
364
365
366         /**
367          * Returns the sync delay. This is the time a syncsource
368          * delays a period signal, e.g. to cope with buffering.
369          * @return the sync delay
370          */
371         unsigned int getSyncDelay() {return m_sync_delay;};
372         /**
373          * sets the sync delay
374          * @param d sync delay
375          */
376         void setSyncDelay(unsigned int d);
377
378         /**
379          * @brief get the maximal frame latency
380          *
381          * The maximum frame latency is the maximum time that will elapse
382          * between the frame being received by the 1394 stack, and the moment this
383          * frame is presented to the StreamProcessor.
384          *
385          * For transmit SP's this is the maximum time that a frame is requested by
386          * the handler ahead of the time the frame is intended to be transmitted.
387          *
388          * This is useful to figure out how longer than the actual reception time
389          * we have to wait before trying to read the frame from the SP.
390          *
391          * @return maximal frame latency
392          */
393         int getMaxFrameLatency();
394
395         float getTicksPerFrame();
396         void setTicksPerFrame(float tpf);
397
398         int getBufferFill();
399
400         // Child implementation interface
401         /**
402         * @brief prepare the child SP
403         * @return true if successful, false otherwise
404         * @pre the m_manager pointer points to a valid manager
405         * @post getEventsPerFrame() returns the correct value
406         * @post getEventSize() returns the correct value
407         * @post getUpdatePeriod() returns the correct value
408         * @post processPacketHeader(...) can be called
409         * @post processPacketData(...) can be called
410         */
411         virtual bool prepareChild() = 0;
412         /**
413          * @brief get the number of events contained in one frame
414          * @return the number of events contained in one frame
415          */
416         virtual unsigned int getEventsPerFrame() = 0;
417
418         /**
419          * @brief get the size of one frame in bytes
420          * @return the size of one frame in bytes
421          */
422         virtual unsigned int getEventSize() = 0;
423
424         /**
425          * @brief get the nominal number of frames in a packet
426          *
427          * This is the amount of frames that is nominally present
428          * in one packet. It is recommended that in the receive handler
429          * you write this amount of frames when a valid packet has
430          * been received. (although this is not mandatory)
431          *
432          * @return the nominal number of frames in a packet
433          */
434         virtual unsigned int getNominalFramesPerPacket() = 0;
435
436         /**
437          * @brief get the nominal number of packets needed for a certain amount of frames
438          * @return the nominal number of packet necessary
439          */
440         virtual unsigned int getNominalPacketsNeeded(unsigned int nframes);
441
442     protected:
443         float m_ticks_per_frame;
444         unsigned int m_sync_delay;
445     private:
446         bool m_in_xrun;
447
448 public:
449     // debug stuff
450     virtual void dumpInfo();
451     virtual void printBufferInfo();
452     virtual void setVerboseLevel(int l);
453     const char *getStateString()
454         {return ePSToString(getState());};
455     const char *getTypeString()
456         {return ePTToString(getType());};
457
458     DECLARE_DEBUG_MODULE;
459 };
460
461 }
462
463 #endif /* __FFADO_STREAMPROCESSOR__ */
464
465
Note: See TracBrowser for help on using the browser.