root/branches/streaming-rework/src/libstreaming/StreamProcessor.cpp

Revision 391, 8.0 kB (checked in by pieterpalmers, 17 years ago)

* Partially finished:

  • Introduce TimestampedBuffer? util class
  • replace interal ringbuffer of SP with timed ringbuffer

* Compiles & works

Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2005,2006 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
29 #include "libutil/Atomic.h"
30
31 #include "StreamProcessor.h"
32 #include "StreamProcessorManager.h"
33 #include "cycletimer.h"
34
35 #include <assert.h>
36
37 namespace FreebobStreaming {
38
39 IMPL_DEBUG_MODULE( StreamProcessor, StreamProcessor, DEBUG_LEVEL_VERBOSE );
40 IMPL_DEBUG_MODULE( ReceiveStreamProcessor, ReceiveStreamProcessor, DEBUG_LEVEL_VERBOSE );
41 IMPL_DEBUG_MODULE( TransmitStreamProcessor, TransmitStreamProcessor, DEBUG_LEVEL_VERBOSE );
42
43 StreamProcessor::StreamProcessor(enum IsoStream::EStreamType type, int port, int framerate)
44         : IsoStream(type, port)
45         , m_nb_buffers(0)
46         , m_period(0)
47         , m_xruns(0)
48         , m_framerate(framerate)
49         , m_manager(NULL)
50         , m_running(false)
51         , m_disabled(true)
52         , m_is_disabled(true)
53         , m_cycle_to_enable_at(0)
54         , m_SyncSource(NULL)
55         , m_ticks_per_frame(0)
56 {
57     // create the timestamped buffer and register ourselves as its client
58     m_data_buffer=new FreebobUtil::TimestampedBuffer(this);
59
60 }
61
62 StreamProcessor::~StreamProcessor() {
63     if (m_data_buffer) delete m_data_buffer;
64 }
65
66 void StreamProcessor::dumpInfo()
67 {
68     debugOutputShort( DEBUG_LEVEL_NORMAL, " StreamProcessor information\n");
69     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Iso stream info:\n");
70    
71     IsoStream::dumpInfo();
72     debugOutputShort( DEBUG_LEVEL_NORMAL, "  StreamProcessor info:\n");
73     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Now                   : %011u\n",m_handler->getCycleTimerTicks());
74     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Xruns                 : %d\n", m_xruns);
75     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Running               : %d\n", m_running);
76     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Enabled               : %s\n", m_disabled ? "No" : "Yes");
77     debugOutputShort( DEBUG_LEVEL_NORMAL, "   enable status        : %s\n", m_is_disabled ? "No" : "Yes");
78    
79     m_data_buffer->dumpInfo();
80    
81 //     m_PeriodStat.dumpInfo();
82 //     m_PacketStat.dumpInfo();
83 //     m_WakeupStat.dumpInfo();
84
85 }
86
87 bool StreamProcessor::init()
88 {
89     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n");
90    
91     m_data_buffer->init();
92    
93     return IsoStream::init();
94 }
95
96 /**
97  * Resets the frame counter, the xrun counter, the ports and the iso stream.
98  * @return true if reset succeeded
99  */
100 bool StreamProcessor::reset() {
101
102     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
103
104     // reset the event buffer, discard all content
105     if (!m_data_buffer->reset()) {
106         debugFatal("Could not reset data buffer\n");
107         return false;
108     }
109    
110     resetXrunCounter();
111
112     // loop over the ports to reset them
113     if (!PortManager::resetPorts()) {
114         debugFatal("Could not reset ports\n");
115         return false;
116     }
117
118     // reset the iso stream
119     if (!IsoStream::reset()) {
120         debugFatal("Could not reset isostream\n");
121         return false;
122     }
123     return true;
124        
125 }
126    
127 bool StreamProcessor::prepareForEnable() {
128     debugOutput(DEBUG_LEVEL_VERBOSE," StreamProcessor::prepareForEnable for (%p)\n",this);
129     debugOutput(DEBUG_LEVEL_VERBOSE," Now                   : %011u\n",m_handler->getCycleTimerTicks());
130     m_data_buffer->dumpInfo();
131     return true;
132 }
133
134 bool StreamProcessor::prepareForDisable() {
135     debugOutput(DEBUG_LEVEL_VERBOSE," StreamProcessor::prepareForDisable for (%p)\n",this);
136     debugOutput(DEBUG_LEVEL_VERBOSE," Now                   : %011u\n",m_handler->getCycleTimerTicks());
137     m_data_buffer->dumpInfo();
138     return true;
139 }
140
141 bool StreamProcessor::prepare() {
142
143         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
144        
145         // init the ports
146        
147         if(!m_manager) {
148                 debugFatal("Not attached to a manager!\n");
149                 return -1;
150         }
151
152         m_nb_buffers=m_manager->getNbBuffers();
153         debugOutput( DEBUG_LEVEL_VERBOSE, "Setting m_nb_buffers  : %d\n", m_nb_buffers);
154
155         m_period=m_manager->getPeriodSize();
156         debugOutput( DEBUG_LEVEL_VERBOSE, "Setting m_period      : %d\n", m_period);
157
158         // loop over the ports to reset them
159         PortManager::preparePorts();
160
161         // reset the iso stream
162         IsoStream::prepare();
163        
164         return true;
165
166 }
167
168 /**
169  * @brief Notify the StreamProcessor that frames were written
170  *
171  * This notifies the StreamProcessor of the fact that frames were written to the internal
172  * buffer. This is for framecounter & timestamp bookkeeping.
173  *
174  * @param nbframes the number of frames that are written to the internal buffers
175  * @param ts the new timestamp of the 'tail' of the buffer, i.e. the last sample
176  *           present in the buffer.
177  * @return true if successful
178  */
179 bool StreamProcessor::putFrames(unsigned int nbframes, int64_t ts) {
180
181         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Putting %d frames for %llu into frame buffer...\n", nbframes,ts);
182         m_data_buffer->incrementFrameCounter(nbframes, ts);
183         return true;
184 }
185
186 /**
187  * @brief Notify the StreamProcessor that frames were read
188  *
189  * This notifies the StreamProcessor of the fact that frames were read from the internal
190  * buffer. This is for framecounter & timestamp bookkeeping.
191  *
192  * @param nbframes the number of frames that are read from the internal buffers
193  * @return true if successful
194  */
195 bool StreamProcessor::getFrames(unsigned int nbframes) {
196
197         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Getting %d frames from frame buffer...\n", nbframes);
198         m_data_buffer->decrementFrameCounter(nbframes);
199         return true;
200 }
201
202 uint64_t StreamProcessor::getTimeNow() {
203     return m_handler->getCycleTimerTicks();
204 }
205
206
207 bool StreamProcessor::isRunning() {
208         return m_running;
209 }
210
211 bool StreamProcessor::enable(uint64_t time_to_enable_at)  {
212     // FIXME: time_to_enable_at will be in 'time' not cycles
213     m_cycle_to_enable_at=time_to_enable_at;
214    
215     if(!m_running) {
216             debugWarning("The StreamProcessor is not running yet, enable() might not be a good idea.\n");
217     }
218
219 #ifdef DEBUG
220     uint64_t now_cycles=TICKS_TO_CYCLES(m_handler->getCycleTimerTicks());
221     const int64_t max=(int64_t)(TICKS_PER_SECOND/2);
222    
223     int64_t diff=m_cycle_to_enable_at-now_cycles;
224    
225     if (diff > max) {
226         diff-=TICKS_PER_SECOND;
227     } else if (diff < -max) {
228         diff+=TICKS_PER_SECOND;
229     }
230    
231     if (diff<0) {
232         debugWarning("Request to enable streamprocessor %d cycles ago.\n",diff);
233     }
234 #endif
235
236     m_disabled=false;
237    
238     return true;
239 }
240
241 bool StreamProcessor::disable()  {
242    
243     m_disabled=true;
244
245     return true;
246
247 }
248
249 bool StreamProcessor::setSyncSource(StreamProcessor *s) {
250     m_SyncSource=s;
251     return true;
252 }
253
254 /**
255  * Resets the xrun counter, in a atomic way. This
256  * is thread safe.
257  */
258 void StreamProcessor::resetXrunCounter() {
259         ZERO_ATOMIC((SInt32 *)&m_xruns);
260 }
261
262 void StreamProcessor::setVerboseLevel(int l) {
263         setDebugLevel(l);
264         IsoStream::setVerboseLevel(l);
265         PortManager::setVerboseLevel(l);
266
267 }
268
269 ReceiveStreamProcessor::ReceiveStreamProcessor(int port, int framerate)
270         : StreamProcessor(IsoStream::EST_Receive, port, framerate) {
271
272 }
273
274 ReceiveStreamProcessor::~ReceiveStreamProcessor() {
275
276 }
277
278 void ReceiveStreamProcessor::setVerboseLevel(int l) {
279         setDebugLevel(l);
280         StreamProcessor::setVerboseLevel(l);
281
282 }
283
284
285 TransmitStreamProcessor::TransmitStreamProcessor( int port, int framerate)
286         : StreamProcessor(IsoStream::EST_Transmit, port, framerate) {
287
288 }
289
290 TransmitStreamProcessor::~TransmitStreamProcessor() {
291
292 }
293
294 void TransmitStreamProcessor::setVerboseLevel(int l) {
295         setDebugLevel(l);
296         StreamProcessor::setVerboseLevel(l);
297
298 }
299
300 }
Note: See TracBrowser for help on using the browser.