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

Revision 734, 8.2 kB (checked in by ppalmers, 13 years ago)

merge ppalmers-streaming branch

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