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

Revision 401, 9.4 kB (checked in by pieterpalmers, 17 years ago)

move some code from amdtp SP to SP base class

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         , m_last_cycle(0)
57         , m_sync_delay(0)
58 {
59     // create the timestamped buffer and register ourselves as its client
60     m_data_buffer=new FreebobUtil::TimestampedBuffer(this);
61
62 }
63
64 StreamProcessor::~StreamProcessor() {
65     if (m_data_buffer) delete m_data_buffer;
66 }
67
68 void StreamProcessor::dumpInfo()
69 {
70     debugOutputShort( DEBUG_LEVEL_NORMAL, " StreamProcessor information\n");
71     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Iso stream info:\n");
72    
73     IsoStream::dumpInfo();
74     debugOutputShort( DEBUG_LEVEL_NORMAL, "  StreamProcessor info:\n");
75     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Now                   : %011u\n",m_handler->getCycleTimerTicks());
76     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Xruns                 : %d\n", m_xruns);
77     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Running               : %d\n", m_running);
78     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Enabled               : %s\n", m_disabled ? "No" : "Yes");
79     debugOutputShort( DEBUG_LEVEL_NORMAL, "   enable status        : %s\n", m_is_disabled ? "No" : "Yes");
80    
81     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Device framerate      : Sync: %f, Buffer %f\n",
82         24576000.0*m_SyncSource->m_data_buffer->getRate(),
83         24576000.0*m_data_buffer->getRate()
84         );
85    
86     m_data_buffer->dumpInfo();
87    
88 //     m_PeriodStat.dumpInfo();
89 //     m_PacketStat.dumpInfo();
90 //     m_WakeupStat.dumpInfo();
91
92 }
93
94 bool StreamProcessor::init()
95 {
96     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n");
97    
98     m_data_buffer->init();
99    
100     return IsoStream::init();
101 }
102
103 /**
104  * Resets the frame counter, the xrun counter, the ports and the iso stream.
105  * @return true if reset succeeded
106  */
107 bool StreamProcessor::reset() {
108
109     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
110
111     // reset the event buffer, discard all content
112     if (!m_data_buffer->reset()) {
113         debugFatal("Could not reset data buffer\n");
114         return false;
115     }
116    
117     resetXrunCounter();
118
119     // loop over the ports to reset them
120     if (!PortManager::resetPorts()) {
121         debugFatal("Could not reset ports\n");
122         return false;
123     }
124
125     // reset the iso stream
126     if (!IsoStream::reset()) {
127         debugFatal("Could not reset isostream\n");
128         return false;
129     }
130     return true;
131        
132 }
133
134 bool StreamProcessor::prepareForEnable(uint64_t time_to_enable_at) {
135     debugOutput(DEBUG_LEVEL_VERBOSE," StreamProcessor::prepareForEnable for (%p)\n",this);
136     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011u\n",m_handler->getCycleTimerTicks());
137     debugOutput(DEBUG_LEVEL_VERBOSE,"  Enable at             : %011u\n",time_to_enable_at);
138     m_data_buffer->dumpInfo();
139     return true;
140 }
141
142 bool StreamProcessor::prepareForDisable() {
143     debugOutput(DEBUG_LEVEL_VERBOSE," StreamProcessor::prepareForDisable for (%p)\n",this);
144     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011u\n",m_handler->getCycleTimerTicks());
145     m_data_buffer->dumpInfo();
146     return true;
147 }
148
149 bool StreamProcessor::prepare() {
150
151         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
152        
153         // init the ports
154        
155         if(!m_manager) {
156                 debugFatal("Not attached to a manager!\n");
157                 return -1;
158         }
159
160         m_nb_buffers=m_manager->getNbBuffers();
161         debugOutput( DEBUG_LEVEL_VERBOSE, "Setting m_nb_buffers  : %d\n", m_nb_buffers);
162
163         m_period=m_manager->getPeriodSize();
164         debugOutput( DEBUG_LEVEL_VERBOSE, "Setting m_period      : %d\n", m_period);
165
166         // loop over the ports to reset them
167         PortManager::preparePorts();
168
169         // reset the iso stream
170         IsoStream::prepare();
171        
172         return true;
173
174 }
175
176 int StreamProcessor::getBufferFill() {
177 //     return m_data_buffer->getFrameCounter();
178     return m_data_buffer->getBufferFill();
179 }
180
181 uint64_t StreamProcessor::getTimeNow() {
182     return m_handler->getCycleTimerTicks();
183 }
184
185
186 bool StreamProcessor::isRunning() {
187         return m_running;
188 }
189
190 bool StreamProcessor::enable(uint64_t time_to_enable_at)  {
191     // FIXME: time_to_enable_at will be in 'time' not cycles
192     m_cycle_to_enable_at=time_to_enable_at;
193    
194     if(!m_running) {
195             debugWarning("The StreamProcessor is not running yet, enable() might not be a good idea.\n");
196     }
197
198 #ifdef DEBUG
199     uint64_t now_cycles=TICKS_TO_CYCLES(m_handler->getCycleTimerTicks());
200     const int64_t max=(int64_t)(TICKS_PER_SECOND/2);
201    
202     int64_t diff=(int64_t)m_cycle_to_enable_at-(int64_t)now_cycles;
203    
204     if (diff > max) {
205         diff-=TICKS_PER_SECOND;
206     } else if (diff < -max) {
207         diff+=TICKS_PER_SECOND;
208     }
209    
210     if (diff<0) {
211         debugWarning("Request to enable streamprocessor %lld cycles ago (now=%llu, cy=%llu).\n",
212             diff,now_cycles,time_to_enable_at);
213     }
214 #endif
215
216     m_disabled=false;
217    
218     return true;
219 }
220
221 bool StreamProcessor::disable()  {
222    
223     m_disabled=true;
224
225     return true;
226
227 }
228
229 bool StreamProcessor::setSyncSource(StreamProcessor *s) {
230     m_SyncSource=s;
231     return true;
232 }
233
234 int64_t StreamProcessor::getTimeUntilNextPeriodUsecs() {
235     uint64_t time_at_period=getTimeAtPeriod();
236    
237     uint64_t cycle_timer=m_handler->getCycleTimerTicks();
238    
239     // calculate the time until the next period
240     int64_t until_next=substractTicks(time_at_period,cycle_timer);
241    
242     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TAP=%11llu, CTR=%11llu, UTN=%11lld\n",
243         time_at_period, cycle_timer, until_next
244         );
245    
246     // now convert to usecs
247     // don't use the mapping function because it only works
248     // for absolute times, not the relative time we are
249     // using here (which can also be negative).
250     return (int64_t)(((float)until_next) / TICKS_PER_USEC);
251 }
252
253 uint64_t StreamProcessor::getTimeAtPeriodUsecs() {
254     return (uint64_t)((float)getTimeAtPeriod() * TICKS_PER_USEC);
255 }
256
257 /**
258  * Resets the xrun counter, in a atomic way. This
259  * is thread safe.
260  */
261 void StreamProcessor::resetXrunCounter() {
262         ZERO_ATOMIC((SInt32 *)&m_xruns);
263 }
264
265 void StreamProcessor::setVerboseLevel(int l) {
266         setDebugLevel(l);
267         IsoStream::setVerboseLevel(l);
268         PortManager::setVerboseLevel(l);
269
270 }
271
272 ReceiveStreamProcessor::ReceiveStreamProcessor(int port, int framerate)
273         : StreamProcessor(IsoStream::EST_Receive, port, framerate) {
274
275 }
276
277 ReceiveStreamProcessor::~ReceiveStreamProcessor() {
278
279 }
280
281 void ReceiveStreamProcessor::setVerboseLevel(int l) {
282         setDebugLevel(l);
283         StreamProcessor::setVerboseLevel(l);
284
285 }
286
287 uint64_t ReceiveStreamProcessor::getTimeAtPeriod() {
288     uint64_t next_period_boundary=m_data_buffer->getTimestampFromHead(m_period);
289    
290     #ifdef DEBUG
291     uint64_t ts,fc;
292     m_data_buffer->getBufferTailTimestamp(&ts,&fc);
293    
294     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD=%11lld, LTS=%11llu, FC=%5u, TPF=%f\n",
295         next_period_boundary, ts, fc, m_ticks_per_frame
296         );
297     #endif
298    
299     return next_period_boundary;
300 }
301
302 bool ReceiveStreamProcessor::canClientTransferFrames(unsigned int nbframes) {
303     return m_data_buffer->getFrameCounter() >= (int) nbframes;
304 }
305
306 TransmitStreamProcessor::TransmitStreamProcessor( int port, int framerate)
307         : StreamProcessor(IsoStream::EST_Transmit, port, framerate) {
308
309 }
310
311 TransmitStreamProcessor::~TransmitStreamProcessor() {
312
313 }
314
315 void TransmitStreamProcessor::setVerboseLevel(int l) {
316         setDebugLevel(l);
317         StreamProcessor::setVerboseLevel(l);
318
319 }
320
321 uint64_t TransmitStreamProcessor::getTimeAtPeriod() {
322     uint64_t next_period_boundary=m_data_buffer->getTimestampFromTail((m_nb_buffers-1) * m_period);
323    
324     #ifdef DEBUG
325     uint64_t ts,fc;
326     m_data_buffer->getBufferTailTimestamp(&ts,&fc);
327    
328     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD=%11lld, LTS=%11llu, FC=%5u, TPF=%f\n",
329         next_period_boundary, ts, fc, m_ticks_per_frame
330         );
331     #endif
332    
333     return next_period_boundary;
334 }
335
336 bool TransmitStreamProcessor::canClientTransferFrames(unsigned int nbframes) {
337     // there has to be enough space to put the frames in
338     return m_data_buffer->getBufferSize() - m_data_buffer->getFrameCounter() > nbframes;
339 }
340
341
342 }
Note: See TracBrowser for help on using the browser.