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

Revision 803, 17.9 kB (checked in by ppalmers, 13 years ago)

more reliable streaming. hackish, but a start for a better implementation

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