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

Revision 385, 19.2 kB (checked in by pieterpalmers, 16 years ago)

- fixed issues with SYT timestamp processing
- SYT based sync works if syncing to the received stream

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) 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 "IsoHandlerManager.h"
30 #include "IsoHandler.h"
31 #include "IsoStream.h"
32 #include <assert.h>
33
34 #define MINIMUM_INTERRUPTS_PER_PERIOD  4U
35 #define PACKETS_PER_INTERRUPT          4U
36
37 namespace FreebobStreaming
38 {
39
40 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
41
42 IsoHandlerManager::IsoHandlerManager() :
43    m_State(E_Created),
44    m_poll_timeout(1), m_poll_fds(0), m_poll_nfds(0)
45 {
46
47 }
48
49
50 IsoHandlerManager::~IsoHandlerManager()
51 {
52
53 }
54
55 bool IsoHandlerManager::Init()
56 {
57         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
58
59         return true;
60 }
61
62 /**
63  * the IsoHandlerManager thread execute function iterates the handlers.
64  *
65  * This means that once the thread is running, streams are
66  * transmitted and received (if present on the bus). Make sure
67  * that the clients are registered & ready before starting the
68  * thread!
69  *
70  * The register and unregister functions are thread unsafe, so
71  * should not be used when the thread is running.
72  *
73  * @return false if the handlers could not be iterated.
74  */
75 bool IsoHandlerManager::Execute()
76 {
77 //     updateCycleTimers();
78    
79     if(!iterate()) {
80         debugFatal("Could not iterate the isoManager\n");
81         return false;
82     }   
83    
84     return true;
85 }
86
87 /**
88  * Poll the handlers managed by this manager, and iterate them
89  * when ready
90  *
91  * @return true when successful
92  */
93 bool IsoHandlerManager::iterate()
94 {
95         int err;
96         int i=0;
97         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n");
98        
99         err = poll (m_poll_fds, m_poll_nfds, m_poll_timeout);
100        
101         if (err == -1) {
102                 if (errno == EINTR) {
103                         return true;
104                 }
105                 debugFatal("poll error: %s\n", strerror (errno));
106                 return false;
107         }
108
109         for (i = 0; i < m_poll_nfds; i++) {
110                 if (m_poll_fds[i].revents & POLLERR) {
111                         debugWarning("error on fd for %d\n",i);
112                 }
113
114                 if (m_poll_fds[i].revents & POLLHUP) {
115                         debugWarning("hangup on fd for %d\n",i);
116                 }
117                
118                 if(m_poll_fds[i].revents & (POLLIN)) {
119                         IsoHandler *s=m_IsoHandlers.at(i);
120                         assert(s);
121                        
122                         s->iterate();
123                 }
124         }
125
126         return true;
127
128 }
129
130 // updates the internal cycle timer caches of the handlers
131 void IsoHandlerManager::updateCycleTimers() {
132     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n");
133    
134     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
135           it != m_IsoHandlers.end();
136           ++it )
137     {
138         int cnt=0;
139         while (!(*it)->updateCycleTimer() && (cnt++ < MAX_UPDATE_TRIES)) {
140             usleep(USLEEP_AFTER_UPDATE_FAILURE);
141         }
142     }
143    
144 }
145
146 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
147 {
148     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
149     assert(handler);
150    
151     m_IsoHandlers.push_back(handler);
152    
153     handler->setVerboseLevel(getDebugLevel());
154
155     // rebuild the fd map for poll()'ing.
156     return rebuildFdMap();     
157
158 }
159
160 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
161 {
162         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
163         assert(handler);
164
165         for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
166           it != m_IsoHandlers.end();
167           ++it )
168         {
169                 if ( *it == handler ) {
170                         // erase the iso handler from the list
171                         m_IsoHandlers.erase(it);
172                         // rebuild the fd map for poll()'ing.
173                         return rebuildFdMap();
174                 }
175         }
176         debugFatal("Could not find handler (%p)\n", handler);
177        
178         return false; //not found
179
180 }
181
182 bool IsoHandlerManager::rebuildFdMap() {
183         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
184         int i=0;
185
186         m_poll_nfds=0;
187         if(m_poll_fds) free(m_poll_fds);
188
189         // count the number of handlers
190         m_poll_nfds=m_IsoHandlers.size();
191
192         // allocate the fd array
193         m_poll_fds   = (struct pollfd *) calloc (m_poll_nfds, sizeof (struct pollfd));
194         if(!m_poll_fds) {
195                 debugFatal("Could not allocate memory for poll FD array\n");
196                 return false;
197         }
198
199         // fill the fd map
200         for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
201           it != m_IsoHandlers.end();
202           ++it )
203         {
204                 m_poll_fds[i].fd=(*it)->getFileDescriptor();
205                 m_poll_fds[i].events = POLLIN;
206                 i++;
207         }
208
209         return true;
210 }
211
212 void IsoHandlerManager::disablePolling(IsoStream *stream) {
213     int i=0;
214    
215     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Disable polling on stream %p\n",stream);
216
217     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
218         it != m_IsoHandlers.end();
219         ++it )
220     {
221         if ((*it)->isStreamRegistered(stream)) {
222             m_poll_fds[i].events = 0;
223             m_poll_fds[i].revents = 0;
224             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "polling disabled\n");
225         }
226        
227         i++;
228     }
229 }
230
231 void IsoHandlerManager::enablePolling(IsoStream *stream) {
232     int i=0;
233    
234     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Enable polling on stream %p\n",stream);
235    
236     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
237         it != m_IsoHandlers.end();
238         ++it )
239     {
240         if ((*it)->isStreamRegistered(stream)) {
241             m_poll_fds[i].events = POLLIN;
242             m_poll_fds[i].revents = 0;
243             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "polling enabled\n");
244         }
245        
246         i++;
247     }
248 }
249
250
251 /**
252  * Registers an IsoStream with the IsoHandlerManager.
253  *
254  * If nescessary, an IsoHandler is created to handle this stream.
255  * Once an IsoStream is registered to the handler, it will be included
256  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
257  *
258  * @param stream the stream to register
259  * @return true if registration succeeds
260  *
261  * \todo : currently there is a one-to-one mapping
262  *        between streams and handlers, this is not ok for
263  *        multichannel receive
264  */
265 bool IsoHandlerManager::registerStream(IsoStream *stream)
266 {
267         debugOutput( DEBUG_LEVEL_VERBOSE, "Registering stream %p\n",stream);
268         assert(stream);
269
270         // make sure the stream isn't already attached to a handler
271         for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
272           it != m_IsoHandlers.end();
273           ++it )
274         {
275                 if((*it)->isStreamRegistered(stream)) {
276                         debugWarning( "stream already registered!\n");
277                         (*it)->unregisterStream(stream);
278                        
279                 }
280         }
281        
282         // clean up all handlers that aren't used
283         pruneHandlers();
284
285         // allocate a handler for this stream
286         if (stream->getType()==IsoStream::EST_Receive) {
287                 // setup the optimal parameters for the raw1394 ISO buffering
288                 unsigned int packets_per_period=stream->getPacketsPerPeriod();
289                
290 #if 0
291                 // hardware interrupts occur when one DMA block is full, and the size of one DMA
292                 // block = PAGE_SIZE. Setting the max_packet_size makes sure that the HW irq is
293                 // occurs at a period boundary (optimal CPU use)
294                
295                 // NOTE: try and use MINIMUM_INTERRUPTS_PER_PERIOD hardware interrupts
296                 //       per period for better latency.
297                 unsigned int max_packet_size=MINIMUM_INTERRUPTS_PER_PERIOD * getpagesize() / packets_per_period;
298                 if (max_packet_size < stream->getMaxPacketSize()) {
299                         max_packet_size=stream->getMaxPacketSize();
300                 }
301
302                 // Ensure we don't request a packet size bigger than the
303                 // kernel-enforced maximum which is currently 1 page.
304                 if (max_packet_size > (unsigned int)getpagesize())
305                         max_packet_size = getpagesize();
306
307                 unsigned int irq_interval=packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
308                 if(irq_interval <= 0) irq_interval=1;
309 #else
310                 // hardware interrupts occur when one DMA block is full, and the size of one DMA
311                 // block = PAGE_SIZE. Setting the max_packet_size enables control over the IRQ
312                 // frequency, as the controller uses max_packet_size, and not the effective size
313                 // when writing to the DMA buffer.
314                
315                 // configure it such that we have an irq for every PACKETS_PER_INTERRUPT packets
316                 unsigned int irq_interval=PACKETS_PER_INTERRUPT;
317                
318                 // unless the period size doesn't allow this
319                 if ((packets_per_period/MINIMUM_INTERRUPTS_PER_PERIOD) < irq_interval) {
320                         irq_interval=1;
321                 }
322                
323                 // FIXME: test
324                 irq_interval=1;
325                
326                 unsigned int max_packet_size=getpagesize() / irq_interval;
327
328                 if (max_packet_size < stream->getMaxPacketSize()) {
329                         max_packet_size=stream->getMaxPacketSize();
330                 }
331
332                 // Ensure we don't request a packet size bigger than the
333                 // kernel-enforced maximum which is currently 1 page.
334                 if (max_packet_size > (unsigned int)getpagesize())
335                         max_packet_size = getpagesize();
336
337 #endif
338                 /* the receive buffer size doesn't matter for the latency,
339                    but it has a minimal value in order for libraw to operate correctly (300) */
340                 int buffers=400;
341                
342                 // create the actual handler
343                 IsoRecvHandler *h = new IsoRecvHandler(stream->getPort(), buffers,
344                                                        max_packet_size, irq_interval);
345
346                 debugOutput( DEBUG_LEVEL_VERBOSE, " registering IsoRecvHandler\n");
347
348                 if(!h) {
349                         debugFatal("Could not create IsoRecvHandler\n");
350                         return false;
351                 }
352
353                 h->setVerboseLevel(getDebugLevel());
354
355                 // init the handler
356                 if(!h->init()) {
357                         debugFatal("Could not initialize receive handler\n");
358                         return false;
359                 }
360
361                 // register the stream with the handler
362                 if(!h->registerStream(stream)) {
363                         debugFatal("Could not register receive stream with handler\n");
364                         return false;
365                 }
366
367                 // register the handler with the manager
368                 if(!registerHandler(h)) {
369                         debugFatal("Could not register receive handler with manager\n");
370                         return false;
371                 }
372                 debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n",stream,h);
373         }
374        
375         if (stream->getType()==IsoStream::EST_Transmit) {
376                 // setup the optimal parameters for the raw1394 ISO buffering
377                 unsigned int packets_per_period=stream->getPacketsPerPeriod();
378
379 #if 0
380                 // hardware interrupts occur when one DMA block is full, and the size of one DMA
381                 // block = PAGE_SIZE. Setting the max_packet_size makes sure that the HW irq 
382                 // occurs at a period boundary (optimal CPU use)
383                 // NOTE: try and use MINIMUM_INTERRUPTS_PER_PERIOD interrupts per period
384                 //       for better latency.
385                 unsigned int max_packet_size=MINIMUM_INTERRUPTS_PER_PERIOD * getpagesize() / packets_per_period;
386                 if (max_packet_size < stream->getMaxPacketSize()) {
387                         max_packet_size=stream->getMaxPacketSize();
388                 }
389
390                 // Ensure we don't request a packet size bigger than the
391                 // kernel-enforced maximum which is currently 1 page.
392                 if (max_packet_size > (unsigned int)getpagesize())
393                         max_packet_size = getpagesize();
394
395                 unsigned int irq_interval=packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
396                 if(irq_interval <= 0) irq_interval=1;
397 #else
398                 // hardware interrupts occur when one DMA block is full, and the size of one DMA
399                 // block = PAGE_SIZE. Setting the max_packet_size enables control over the IRQ
400                 // frequency, as the controller uses max_packet_size, and not the effective size
401                 // when writing to the DMA buffer.
402                
403                 // configure it such that we have an irq for every PACKETS_PER_INTERRUPT packets
404                 unsigned int irq_interval=PACKETS_PER_INTERRUPT;
405                
406                 // unless the period size doesn't allow this
407                 if ((packets_per_period/MINIMUM_INTERRUPTS_PER_PERIOD) < irq_interval) {
408                         irq_interval=1;
409                 }
410                
411                 // FIXME: test
412                 irq_interval=1;
413
414                 unsigned int max_packet_size=getpagesize() / irq_interval;
415
416                 if (max_packet_size < stream->getMaxPacketSize()) {
417                         max_packet_size=stream->getMaxPacketSize();
418                 }
419
420                 // Ensure we don't request a packet size bigger than the
421                 // kernel-enforced maximum which is currently 1 page.
422                 if (max_packet_size > (unsigned int)getpagesize())
423                         max_packet_size = getpagesize();
424 #endif
425                 // the transmit buffer size should be as low as possible for latency.
426                 // note however that the raw1394 subsystem tries to keep this buffer
427                 // full, so we have to make sure that we have enough events in our
428                 // event buffers
429                
430                 // every irq_interval packets an interrupt will occur. that is when
431                 // buffers get transfered, meaning that we should have at least some
432                 // margin here
433 //              int buffers=irq_interval * 2;
434
435                 // half a period. the xmit handler will take care of this
436                 int buffers=packets_per_period/2;
437                
438                 // NOTE: this is dangerous: what if there is not enough prefill?
439 //              if (buffers<10) buffers=10;     
440                
441                 // create the actual handler
442                 IsoXmitHandler *h = new IsoXmitHandler(stream->getPort(), buffers,
443                                                        max_packet_size, irq_interval);
444
445                 debugOutput( DEBUG_LEVEL_VERBOSE, " registering IsoXmitHandler\n");
446
447                 if(!h) {
448                         debugFatal("Could not create IsoXmitHandler\n");
449                         return false;
450                 }
451
452                 h->setVerboseLevel(getDebugLevel());
453
454                 // init the handler
455                 if(!h->init()) {
456                         debugFatal("Could not initialize transmit handler\n");
457                         return false;
458                 }
459
460                 // register the stream with the handler
461                 if(!h->registerStream(stream)) {
462                         debugFatal("Could not register transmit stream with handler\n");
463                         return false;
464                 }
465
466                 // register the handler with the manager
467                 if(!registerHandler(h)) {
468                         debugFatal("Could not register transmit handler with manager\n");
469                         return false;
470                 }
471                 debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n",stream,h);
472
473         }
474
475         m_IsoStreams.push_back(stream);
476         debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
477                                           m_IsoStreams.size(), m_IsoHandlers.size());
478
479         return true;
480 }
481
482 bool IsoHandlerManager::unregisterStream(IsoStream *stream)
483 {
484         debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering stream %p\n",stream);
485         assert(stream);
486
487         // make sure the stream isn't attached to a handler anymore
488         for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
489           it != m_IsoHandlers.end();
490           ++it )
491         {
492                 if((*it)->isStreamRegistered(stream)) {
493                         if(!(*it)->unregisterStream(stream)) {
494                                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
495                                 return false;
496                         }
497                        
498                         debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
499                 }
500         }
501
502         // clean up all handlers that aren't used
503         pruneHandlers();
504
505         // remove the stream from the registered streams list
506         for ( IsoStreamVectorIterator it = m_IsoStreams.begin();
507           it != m_IsoStreams.end();
508           ++it )
509         {
510                 if ( *it == stream ) {
511                         m_IsoStreams.erase(it);
512                        
513                         debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
514                         return true;
515                 }
516         }
517
518         return false; //not found
519
520 }
521
522 void IsoHandlerManager::pruneHandlers() {
523     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
524     IsoHandlerVector toUnregister;
525
526     // find all handlers that are not in use
527     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
528           it != m_IsoHandlers.end();
529           ++it )
530     {
531         if(!((*it)->inUse())) {
532             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
533             toUnregister.push_back(*it);
534         }
535     }
536     // delete them
537     for ( IsoHandlerVectorIterator it = toUnregister.begin();
538           it != toUnregister.end();
539           ++it )
540     {
541         unregisterHandler(*it);
542         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
543
544         // Now the handler's been unregistered it won't be reused
545         // again.  Therefore it really needs to be formally deleted
546         // to free up the raw1394 handle.  Otherwise things fall
547         // apart after several xrun recoveries as the system runs
548         // out of resources to support all the disused but still
549         // allocated raw1394 handles.  At least this is the current
550         // theory as to why we end up with "memory allocation"
551         // failures after several Xrun recoveries.
552         delete *it;
553     }
554
555 }
556
557
558 bool IsoHandlerManager::prepare()
559 {
560     bool retval=true;
561    
562     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
563    
564     // check state
565     if(m_State != E_Created) {
566         debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State);
567         return false;
568     }
569    
570     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
571           it != m_IsoHandlers.end();
572           ++it )
573     {
574         if(!(*it)->prepare()) {
575             debugFatal("Could not prepare handlers\n");
576             retval=false;
577         }
578     }
579
580     if (retval) {
581         m_State=E_Prepared;
582     } else {
583         m_State=E_Error;
584     }
585
586     return retval;
587 }
588
589 bool IsoHandlerManager::startHandlers() {
590     return startHandlers(-1);
591 }
592
593 bool IsoHandlerManager::startHandlers(int cycle) {
594     bool retval=true;
595    
596     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
597    
598     // check state
599     if(m_State != E_Prepared) {
600         debugError("Incorrect state, expected E_Prepared, got %d\n",(int)m_State);
601         return false;
602     }
603    
604     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
605         it != m_IsoHandlers.end();
606         ++it )
607     {
608         debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler (%p)\n",*it);
609         if(!(*it)->start(cycle)) {
610             debugOutput( DEBUG_LEVEL_VERBOSE, " could not start handler (%p)\n",*it);
611             retval=false;
612         }
613     }
614    
615     if (retval) {
616         m_State=E_Running;
617     } else {
618         m_State=E_Error;
619     }
620
621     return retval;
622 }
623
624 bool IsoHandlerManager::stopHandlers() {
625     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
626    
627     // check state
628     if(m_State != E_Running) {
629         debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State);
630         return false;
631     }
632    
633     bool retval=true;
634    
635     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
636         it != m_IsoHandlers.end();
637         ++it )
638     {
639         debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler (%p)\n",*it);
640         if(!(*it)->stop()){
641             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
642             retval=false;
643         }
644     }
645    
646     if (retval) {
647         m_State=E_Prepared;
648     } else {
649         m_State=E_Error;
650     }
651    
652     return retval;
653 }
654
655 bool IsoHandlerManager::reset() {
656     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
657    
658     // check state
659     if(m_State == E_Error) {
660         debugFatal("Resetting from error condition not yet supported...\n");
661         return false;
662     }
663    
664     // if not in an error condition, reset means stop the handlers
665     return stopHandlers();
666 }
667
668
669 void IsoHandlerManager::setVerboseLevel(int i) {
670     setDebugLevel(i);
671
672     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
673           it != m_IsoHandlers.end();
674           ++it )
675     {
676         (*it)->setVerboseLevel(i);
677     }
678 }
679
680 void IsoHandlerManager::dumpInfo() {
681     int i=0;
682    
683     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
684     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
685
686     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
687           it != m_IsoHandlers.end();
688           ++it )
689     {
690         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
691
692         (*it)->dumpInfo();
693     }
694
695 }
696
697 } // end of namespace FreebobStreaming
698
Note: See TracBrowser for help on using the browser.