root/trunk/libffado/src/libutil/TimestampedBuffer.h

Revision 512, 6.9 kB (checked in by jwoithe, 16 years ago)

MOTU: more tweaks to improve reliability. Things are looking pretty good now.
MOTU: Commenced cleanup of MOTU code, removing temporary debug output etc.

Line 
1 /* $Id$ */
2
3 /*
4  *   FFADO Streaming API
5  *   FFADO = Firewire (pro-)audio for linux
6  *
7  *   http://ffado.sf.net
8  *
9  *   Copyright (C) 2005,2006,2007 Pieter Palmers <pieterpalmers@users.sourceforge.net>
10  *
11  *   This program is free software {} you can redistribute it and/or modify
12  *   it under the terms of the GNU General Public License as published by
13  *   the Free Software Foundation {} either version 2 of the License, or
14  *   (at your option) any later version.
15  *
16  *   This program is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program {} if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  *
26  *
27  */
28 #ifndef __FFADO_TIMESTAMPEDBUFFER__
29 #define __FFADO_TIMESTAMPEDBUFFER__
30
31 #include "../debugmodule/debugmodule.h"
32 #include "libutil/ringbuffer.h"
33
34 //typedef float ffado_timestamp_t;
35 //#define TIMESTAMP_FORMAT_SPEC "%14.3f"
36 typedef double ffado_timestamp_t;
37 #define TIMESTAMP_FORMAT_SPEC "%14.3f"
38 // typedef int64_t ffado_timestamp_t;
39 // #define TIMESTAMP_FORMAT_SPEC "%012lld"
40
41 namespace Util {
42
43
44 class TimestampedBufferClient;
45
46 /**
47  * \brief Class implementing a frame buffer that is time-aware
48  *
49  * This class implements a buffer that is time-aware. Whenever new frames
50  * are written to the buffer, the timestamp corresponding to the last frame
51  * in the buffer is updated. This allows to calculate the timestamp of any
52  * other frame in the buffer.
53  *
54  * The buffer is a frame buffer, having the following parameters defining
55  * it's behaviour:
56  * - buff_size: buffer size in frames (setBufferSize())
57  * - events_per_frame: the number of events per frame (setEventsPerFrame())
58  * - event_size: the storage size of the events (in bytes) (setEventSize())
59  *
60  * The total size of the buffer (in bytes) is at least
61  * buff_size*events_per_frame*event_size.
62  *
63  * Timestamp tracking is done by requiring that a timestamp is specified every
64  * time frames are added to the buffer. In combination with the buffer fill and
65  * the frame rate (calculated internally), this allows to calculate the timestamp
66  * of any frame in the buffer. In order to initialize the internal data structures,
67  * the setNominalRate() and setUpdatePeriod() functions are provided.
68  *
69  * \note Currently the class only supports fixed size writes of size update_period.
70  *       This can change in the future, implementation ideas are already in place.
71  *
72  * The TimestampedBuffer class is time unit agnostic. It can handle any time unit
73  * as long as it fits in a 64 bit unsigned integer. The buffer supports wrapped
74  * timestamps using (...).
75  *
76  * There are two methods of reading and writing to the buffer.
77  *
78  * The first method uses conventional readFrames() and writeFrames() functions.
79  *
80  * The second method makes use of the TimestampedBufferClient interface. When a
81  * TimestampedBuffer is created, it is required that a TimestampedBufferClient is
82  * registered. This client implements the processReadBlock and processWriteBlock
83  * functions. These are block processing 'callbacks' that allow zero-copy processing
84  * of the buffer contents. In order to initiate block processing, the
85  * blockProcessWriteFrames and blockProcessReadFrames functions are provided by
86  * TimestampedBuffer.
87  *
88  */
89 class TimestampedBuffer {
90
91 public:
92
93
94     TimestampedBuffer(TimestampedBufferClient *);
95     virtual ~TimestampedBuffer();
96    
97     bool writeDummyFrame();
98    
99     bool writeFrames(unsigned int nbframes, char *data, ffado_timestamp_t ts);
100     bool readFrames(unsigned int nbframes, char *data);
101
102     bool blockProcessWriteFrames(unsigned int nbframes, ffado_timestamp_t ts);
103     bool blockProcessReadFrames(unsigned int nbframes);
104
105     bool init();
106     bool prepare();
107     bool reset();
108
109     bool setEventSize(unsigned int s);
110     bool setEventsPerFrame(unsigned int s);
111     bool setBufferSize(unsigned int s);
112     unsigned int getBufferSize() {return m_buffer_size;};
113
114     unsigned int getBytesPerFrame() {return m_bytes_per_frame;};
115
116     bool setWrapValue(ffado_timestamp_t w);
117
118     unsigned int getBufferFill();
119
120     // timestamp stuff
121     int getFrameCounter() {return m_framecounter;};
122
123     void getBufferHeadTimestamp(ffado_timestamp_t *ts, signed int *fc);
124     void getBufferTailTimestamp(ffado_timestamp_t *ts, signed int *fc);
125
126     void setBufferTailTimestamp(ffado_timestamp_t new_timestamp);
127     void setBufferHeadTimestamp(ffado_timestamp_t new_timestamp);
128
129     ffado_timestamp_t getTimestampFromTail(int nframes);
130     ffado_timestamp_t getTimestampFromHead(int nframes);
131
132     // buffer offset stuff
133     /// return the tick offset value
134     ffado_timestamp_t getTickOffset() {return m_tick_offset;};
135
136     bool setFrameOffset(int nframes);
137     bool setTickOffset(ffado_timestamp_t);
138
139     // dll stuff
140     bool setNominalRate(float r);
141     float getRate();
142
143     bool setUpdatePeriod(unsigned int t);
144
145     // misc stuff
146     void dumpInfo();
147     void setVerboseLevel(int l) {setDebugLevel(l);};
148
149 private:
150     void decrementFrameCounter(int nbframes);
151     void incrementFrameCounter(int nbframes, ffado_timestamp_t new_timestamp);
152     void resetFrameCounter();
153
154 protected:
155
156     ffado_ringbuffer_t * m_event_buffer;
157     char* m_cluster_buffer;
158
159     unsigned int m_event_size; // the size of one event
160     unsigned int m_events_per_frame; // the number of events in a frame
161     unsigned int m_buffer_size; // the number of frames in the buffer
162     unsigned int m_bytes_per_frame;
163     unsigned int m_bytes_per_buffer;
164
165     ffado_timestamp_t m_wrap_at; // value to wrap at
166
167     TimestampedBufferClient *m_Client;
168
169     DECLARE_DEBUG_MODULE;
170
171 private:
172     // the framecounter gives the number of frames in the buffer
173     signed int m_framecounter;
174
175     // the offset that define the timing of the buffer
176     ffado_timestamp_t m_tick_offset;
177
178     // the buffer tail timestamp gives the timestamp of the last frame
179     // that was put into the buffer
180     ffado_timestamp_t   m_buffer_tail_timestamp;
181     ffado_timestamp_t   m_buffer_next_tail_timestamp;
182
183     // this mutex protects the access to the framecounter
184     // and the buffer head timestamp.
185     pthread_mutex_t m_framecounter_lock;
186
187     // tracking DLL variables
188 // JMW: try double for this too
189 //    float m_dll_e2;
190     double m_dll_e2;
191     float m_dll_b;
192     float m_dll_c;
193
194     float m_nominal_rate;
195     unsigned int m_update_period;
196 };
197
198 /**
199  * \brief Interface to be implemented by TimestampedBuffer clients
200  */
201 class TimestampedBufferClient {
202     public:
203         TimestampedBufferClient() {};
204         virtual ~TimestampedBufferClient() {};
205
206         virtual bool processReadBlock(char *data, unsigned int nevents, unsigned int offset)=0;
207         virtual bool processWriteBlock(char *data, unsigned int nevents, unsigned int offset)=0;
208
209 };
210
211 } // end of namespace Util
212
213 #endif /* __FFADO_TIMESTAMPEDBUFFER__ */
214
215
Note: See TracBrowser for help on using the browser.