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

Revision 1531, 17.5 kB (checked in by ppalmers, 13 years ago)

svn merge -r 1506:HEAD svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

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