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

Revision 393, 49.8 kB (checked in by pieterpalmers, 17 years ago)

- fixed some bugs in the timestampedbuffer
- cleaned up the amdtpstreamprocessor
- updated test-sytmonitor and test-cycletimer

to the new threading structure

- implemented test for timestampedbuffer

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 "AmdtpStreamProcessor.h"
30 #include "Port.h"
31 #include "AmdtpPort.h"
32
33 #include "cycletimer.h"
34
35 #include <netinet/in.h>
36 #include <assert.h>
37
38 #define RECEIVE_DLL_INTEGRATION_COEFFICIENT 0.015
39
40 #define RECEIVE_PROCESSING_DELAY (10000U)
41
42 // in ticks
43 #define TRANSMIT_TRANSFER_DELAY 9000U
44 // the number of cycles to send a packet in advance of it's timestamp
45 #define TRANSMIT_ADVANCE_CYCLES 1U
46
47 namespace FreebobStreaming {
48
49 IMPL_DEBUG_MODULE( AmdtpTransmitStreamProcessor, AmdtpTransmitStreamProcessor, DEBUG_LEVEL_NORMAL );
50 IMPL_DEBUG_MODULE( AmdtpReceiveStreamProcessor, AmdtpReceiveStreamProcessor, DEBUG_LEVEL_NORMAL );
51
52
53 /* transmit */
54 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(int port, int framerate, int dimension)
55         : TransmitStreamProcessor(port, framerate), m_dimension(dimension)
56         , m_last_timestamp(0), m_dbc(0), m_ringbuffer_size_frames(0)
57 {
58
59 }
60
61 AmdtpTransmitStreamProcessor::~AmdtpTransmitStreamProcessor() {
62
63 }
64
65 /**
66  * @return
67  */
68 bool AmdtpTransmitStreamProcessor::init() {
69
70         debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing (%p)...\n");
71         // call the parent init
72         // this has to be done before allocating the buffers,
73         // because this sets the buffersizes from the processormanager
74         if(!TransmitStreamProcessor::init()) {
75                 debugFatal("Could not do base class init (%p)\n",this);
76                 return false;
77         }
78        
79         return true;
80 }
81
82 void AmdtpTransmitStreamProcessor::setVerboseLevel(int l) {
83         setDebugLevel(l);
84         TransmitStreamProcessor::setVerboseLevel(l);
85 }
86
87 enum raw1394_iso_disposition
88 AmdtpTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length,
89                       unsigned char *tag, unsigned char *sy,
90                       int cycle, unsigned int dropped, unsigned int max_length) {
91    
92     struct iec61883_packet *packet = (struct iec61883_packet *) data;
93    
94     m_last_cycle=cycle;
95    
96     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Xmit handler for cycle %d, (running=%d, enabled=%d,%d)\n",
97         cycle, m_running, m_disabled, m_is_disabled);
98    
99 #ifdef DEBUG
100     if(dropped>0) {
101         debugWarning("Dropped %d packets on cycle %d\n",dropped, cycle);
102     }
103 #endif
104    
105     // calculate & preset common values
106    
107     /* Our node ID can change after a bus reset, so it is best to fetch
108      * our node ID for each packet. */
109     packet->sid = getNodeId() & 0x3f;
110
111     packet->dbs = m_dimension;
112     packet->fn = 0;
113     packet->qpc = 0;
114     packet->sph = 0;
115     packet->reserved = 0;
116     packet->dbc = m_dbc;
117     packet->eoh1 = 2;
118     packet->fmt = IEC61883_FMT_AMDTP;
119    
120     *tag = IEC61883_TAG_WITH_CIP;
121     *sy = 0;
122    
123     // determine if we want to send a packet or not
124     // note that we can't use getCycleTimer directly here,
125     // because packets are queued in advance. This means that
126     // we the packet we are constructing will be sent out
127     // on 'cycle', not 'now'.
128     unsigned int ctr=m_handler->getCycleTimer();
129     int now_cycles = (int)CYCLE_TIMER_GET_CYCLES(ctr);
130    
131     // the difference between 'now' and the cycle this
132     // packet is intended for
133     int cycle_diff = substractCycles(cycle, now_cycles);
134    
135 #ifdef DEBUG
136     if(cycle_diff < 0) {
137         debugWarning("Requesting packet for cycle %04d which is in the past (now=%04dcy)\n",
138             cycle, now_cycles);
139     }
140 #endif
141
142     // as long as the cycle parameter is not in sync with
143     // the current time, the stream is considered not
144     // to be 'running'
145     // NOTE: this works only at startup
146     if (!m_running && cycle_diff >= 0 && cycle != -1) {
147             debugOutput(DEBUG_LEVEL_VERBOSE, "Xmit StreamProcessor %p started running at cycle %d\n",this, cycle);
148             m_running=true;
149     }
150    
151     uint64_t ts_head, fc;
152     if (!m_disabled && m_is_disabled) {
153         // this means that we are trying to enable
154         if ((unsigned int)cycle == m_cycle_to_enable_at) {
155             m_is_disabled=false;
156            
157             debugOutput(DEBUG_LEVEL_VERBOSE,"Enabling StreamProcessor %p at %u\n", this, cycle);
158            
159             // initialize the buffer head & tail
160             m_SyncSource->m_data_buffer->getBufferHeadTimestamp(&ts_head, &fc); // thread safe
161            
162             // the number of cycles the sync source lags (> 0)
163             // or leads (< 0)
164             int sync_lag_cycles=substractCycles(cycle, m_SyncSource->getLastCycle());
165            
166             // account for the cycle lag between sync SP and this SP
167             // the last update of the sync source's timestamps was sync_lag_cycles
168             // cycles before the cycle we are calculating the timestamp for.
169             // if we were to use one-frame buffers, you would expect the
170             // frame that is sent on cycle CT to have a timestamp T1.
171             // ts_head however is for cycle CT-sync_lag_cycles, and lies
172             // therefore sync_lag_cycles * TICKS_PER_CYCLE earlier than
173             // T1.
174             ts_head += sync_lag_cycles * TICKS_PER_CYCLE;
175
176             float ticks_per_frame=m_SyncSource->getTicksPerFrame();
177
178             // calculate the buffer tail timestamp of our buffer
179             // this timestamp corresponds to the buffer head timestamp
180             // of the sync source plus the 'length' of our buffer.
181             // this makes the buffer head timestamp of our buffer
182             // equal to (at max) the buffer head timestamp of the
183             // sync source.
184             ts_head = addTicks(ts_head, (uint32_t)((float)m_ringbuffer_size_frames * ticks_per_frame));
185            
186             #ifdef DEBUG
187             if ((unsigned int)m_data_buffer->getFrameCounter() != m_ringbuffer_size_frames) {
188                 debugWarning("m_data_buffer->getFrameCounter() != m_ringbuffer_size_frames\n");
189             }
190             #endif
191
192             m_data_buffer->setBufferTailTimestamp(ts_head);
193
194             debugOutput(DEBUG_LEVEL_VERBOSE,"XMIT TS SET: TS=%10lld, FC=%4d, %f\n",
195                             ts_head, m_data_buffer->getFrameCounter(), ticks_per_frame);
196         } else {
197             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
198                         "will enable StreamProcessor %p at %u, now is %d\n",
199                         this, m_cycle_to_enable_at, cycle);
200         }
201     } else if (m_disabled && !m_is_disabled) {
202         // trying to disable
203         debugOutput(DEBUG_LEVEL_VERBOSE,"disabling StreamProcessor %p at %u\n",
204                     this, cycle);
205         m_is_disabled=true;
206     }
207    
208     // the base timestamp is the one of the next sample in the buffer
209     m_data_buffer->getBufferHeadTimestamp(&ts_head, &fc); // thread safe
210    
211     int64_t timestamp = ts_head;
212
213     // we send a packet some cycles in advance, to avoid the
214     // following situation:
215     // suppose we are only a few ticks away from
216     // the moment to send this packet. therefore we decide
217     // not to send the packet, but send it in the next cycle.
218     // This means that the next time point will be 3072 ticks
219     // later, making that the timestamp will be expired when the
220     // packet is sent, unless TRANSFER_DELAY > 3072.
221     // this means that we need at least one cycle of extra buffering.
222     uint64_t ticks_to_advance = TICKS_PER_CYCLE * TRANSMIT_ADVANCE_CYCLES;
223    
224     // if cycle lies cycle_diff cycles in the future, we should
225     // queue this packet cycle_diff * TICKS_PER_CYCLE earlier than
226     // we would if it were to be sent immediately.
227     ticks_to_advance += cycle_diff * TICKS_PER_CYCLE;
228
229     // determine the 'now' time in ticks
230     uint64_t cycle_timer=CYCLE_TIMER_TO_TICKS(ctr);
231    
232     // time until the packet is to be sent (if > 0: send packet)
233     int64_t until_next=substractTicks(timestamp, cycle_timer + ticks_to_advance);
234
235 #ifdef DEBUG
236     if(!m_is_disabled) {
237         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " > TS=%11llu, CTR=%11llu, FC=%5d\n",
238             timestamp, cycle_timer, fc
239             );
240         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "    UTN=%11lld\n",
241             until_next
242             );
243         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "    CY_NOW=%04d, CY_TARGET=%04d, CY_DIFF=%04d\n",
244             now_cycles, cycle, cycle_diff
245             );
246     }
247 #endif
248    
249     // don't process the stream when it is not enabled, not running
250     // or when the next sample is not due yet.
251    
252     // we do have to generate (semi) valid packets
253     // that means that we'll send NODATA packets.
254     if((until_next>0) || m_is_disabled || !m_running) {
255         // no-data packets have syt=0xFFFF
256         // and have the usual amount of events as dummy data (?)
257         packet->fdf = IEC61883_FDF_NODATA;
258         packet->syt = 0xffff;
259        
260         // FIXME: either make this a setting or choose
261         bool send_payload=true;
262         if(send_payload) {
263             // the dbc is incremented even with no data packets
264             m_dbc += m_syt_interval;
265    
266             // this means no-data packets with payload (DICE doesn't like that)
267             *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t);
268         } else {
269             // dbc is not incremented
270            
271             // this means no-data packets without payload
272             *length = 2*sizeof(quadlet_t);
273         }
274
275         return RAW1394_ISO_DEFER;
276     }
277    
278     // construct the packet
279    
280     // add the transmit transfer delay to construct the playout time (=SYT timestamp)
281     uint64_t ts=addTicks(timestamp, TRANSMIT_TRANSFER_DELAY);
282
283     unsigned int nevents = m_syt_interval;
284     if (m_data_buffer->readFrames(nevents, (char *)(data + 8))) {
285    
286         m_dbc += m_syt_interval;
287        
288         packet->fdf = m_fdf;
289
290         // convert the timestamp to SYT format
291         uint16_t timestamp_SYT = TICKS_TO_SYT(ts);
292         packet->syt = ntohs(timestamp_SYT);
293        
294         *length = nevents*sizeof(quadlet_t)*m_dimension + 8;
295
296         // process all ports that should be handled on a per-packet base
297         // this is MIDI for AMDTP (due to the need of DBC)
298         if (!encodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) {
299             debugWarning("Problem encoding Packet Ports\n");
300         }
301
302         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT: CY=%04u TS=%011llu TSS=%011llu\n",
303             cycle, timestamp, ts);
304
305         return RAW1394_ISO_OK;
306        
307     } else { // there is no more data in the ringbuffer
308
309         // TODO: maybe we have to be a little smarter here
310         //       because we have some slack on the device side (TRANSFER_DELAY)
311         //       we can allow some skipped packets
312         debugWarning("Transmit buffer underrun (now %d, queue %d, target %d)\n",
313                  now_cycles, cycle, TICKS_TO_CYCLES(ts));
314
315         // signal underrun
316         m_xruns++;
317
318         // disable the processing, will be re-enabled when
319         // the xrun is handled
320         m_disabled=true;
321         m_is_disabled=true;
322
323         // compose a no-data packet, we should always
324         // send a valid packet
325        
326         // FIXME: either make this a setting or choose
327         bool send_payload=true;
328         if(send_payload) {
329             // the dbc is incremented even with no data packets
330             m_dbc += m_syt_interval;
331    
332             // this means no-data packets with payload (DICE doesn't like that)
333             *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t);
334         } else {
335             // dbc is not incremented
336            
337             // this means no-data packets without payload
338             *length = 2*sizeof(quadlet_t);
339         }
340
341         return RAW1394_ISO_DEFER;
342     }
343
344     // we shouldn't get here
345     return RAW1394_ISO_ERROR;
346
347 }
348
349 int64_t AmdtpTransmitStreamProcessor::getTimeUntilNextPeriodUsecs() {
350     debugFatal("IMPLEMENT ME!");
351     return 0;
352 }
353
354 uint64_t AmdtpTransmitStreamProcessor::getTimeAtPeriodUsecs() {
355     // then we should convert this into usecs
356     // FIXME: we assume that the TimeSource of the IsoHandler is
357     //        in usecs.
358     return m_handler->mapToTimeSource(getTimeAtPeriod());
359 }
360
361 uint64_t AmdtpTransmitStreamProcessor::getTimeAtPeriod() {
362     debugFatal("IMPLEMENT ME!");
363    
364     return 0;
365 }
366
367 bool AmdtpTransmitStreamProcessor::prefill() {
368
369     debugOutput( DEBUG_LEVEL_VERBOSE, "Prefill transmit buffers...\n");
370    
371     if(!transferSilence(m_ringbuffer_size_frames)) {
372         debugFatal("Could not prefill transmit stream\n");
373         return false;
374     }
375
376     return true;
377 }
378
379 bool AmdtpTransmitStreamProcessor::reset() {
380
381     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
382
383     // reset the statistics
384     m_PeriodStat.reset();
385     m_PacketStat.reset();
386     m_WakeupStat.reset();
387    
388     // reset all non-device specific stuff
389     // i.e. the iso stream and the associated ports
390     if(!TransmitStreamProcessor::reset()) {
391         debugFatal("Could not do base class reset\n");
392         return false;
393     }
394    
395     // we should prefill the event buffer
396     if (!prefill()) {
397         debugFatal("Could not prefill buffers\n");
398         return false;   
399     }
400    
401     return true;
402 }
403
404 bool AmdtpTransmitStreamProcessor::prepare() {
405     m_PeriodStat.setName("XMT PERIOD");
406     m_PacketStat.setName("XMT PACKET");
407     m_WakeupStat.setName("XMT WAKEUP");
408
409     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
410    
411     // prepare all non-device specific stuff
412     // i.e. the iso stream and the associated ports
413     if(!TransmitStreamProcessor::prepare()) {
414         debugFatal("Could not prepare base class\n");
415         return false;
416     }
417    
418     switch (m_framerate) {
419     case 32000:
420         m_syt_interval = 8;
421         m_fdf = IEC61883_FDF_SFC_32KHZ;
422         break;
423     case 44100:
424         m_syt_interval = 8;
425         m_fdf = IEC61883_FDF_SFC_44K1HZ;
426         break;
427     default:
428     case 48000:
429         m_syt_interval = 8;
430         m_fdf = IEC61883_FDF_SFC_48KHZ;
431         break;
432     case 88200:
433         m_syt_interval = 16;
434         m_fdf = IEC61883_FDF_SFC_88K2HZ;
435         break;
436     case 96000:
437         m_syt_interval = 16;
438         m_fdf = IEC61883_FDF_SFC_96KHZ;
439         break;
440     case 176400:
441         m_syt_interval = 32;
442         m_fdf = IEC61883_FDF_SFC_176K4HZ;
443         break;
444     case 192000:
445         m_syt_interval = 32;
446         m_fdf = IEC61883_FDF_SFC_192KHZ;
447         break;
448     }
449    
450     iec61883_cip_init (
451         &m_cip_status,
452         IEC61883_FMT_AMDTP,
453         m_fdf,
454         m_framerate,
455         m_dimension,
456         m_syt_interval);
457
458     // prepare the framerate estimate
459     m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate);
460    
461     // allocate the event buffer
462     m_ringbuffer_size_frames=m_nb_buffers * m_period;
463
464     // add the receive processing delay
465 //     m_ringbuffer_size_frames+=(uint)(RECEIVE_PROCESSING_DELAY/m_ticks_per_frame);
466
467     assert(m_data_buffer);   
468     m_data_buffer->setBufferSize(m_ringbuffer_size_frames);
469     m_data_buffer->setEventSize(sizeof(quadlet_t));
470     m_data_buffer->setEventsPerFrame(m_dimension);
471    
472     m_data_buffer->setUpdatePeriod(m_period);
473     m_data_buffer->setNominalRate(m_ticks_per_frame);
474    
475     m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND);
476    
477     m_data_buffer->prepare();
478
479     // set the parameters of ports we can:
480     // we want the audio ports to be period buffered,
481     // and the midi ports to be packet buffered
482     for ( PortVectorIterator it = m_Ports.begin();
483           it != m_Ports.end();
484           ++it )
485     {
486         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
487         if(!(*it)->setBufferSize(m_period)) {
488             debugFatal("Could not set buffer size to %d\n",m_period);
489             return false;
490         }
491        
492        
493         switch ((*it)->getPortType()) {
494             case Port::E_Audio:
495                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
496                     debugFatal("Could not set signal type to PeriodSignalling");
497                     return false;
498                 }
499                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
500                 // buffertype and datatype are dependant on the API
501                 if(!(*it)->setBufferType(Port::E_PointerBuffer)) {
502                     debugFatal("Could not set buffer type");
503                     return false;
504                 }
505                 if(!(*it)->useExternalBuffer(true)) {
506                     debugFatal("Could not set external buffer usage");
507                     return false;
508                 }
509                
510                 if(!(*it)->setDataType(Port::E_Float)) {
511                     debugFatal("Could not set data type");
512                     return false;
513                 }
514                
515                
516                 break;
517             case Port::E_Midi:
518                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
519                     debugFatal("Could not set signal type to PeriodSignalling");
520                     return false;
521                 }
522                
523                 // we use a timing unit of 10ns
524                 // this makes sure that for the max syt interval
525                 // we don't have rounding, and keeps the numbers low
526                 // we have 1 slot every 8 events
527                 // we have syt_interval events per packet
528                 // => syt_interval/8 slots per packet
529                 // packet rate is 8000pkt/sec => interval=125us
530                 // so the slot interval is (1/8000)/(syt_interval/8)
531                 // or: 1/(1000 * syt_interval) sec
532                 // which is 1e9/(1000*syt_interval) nsec
533                 // or 100000/syt_interval 'units'
534                 // the event interval is fixed to 320us = 32000 'units'
535                 if(!(*it)->useRateControl(true,(100000/m_syt_interval),32000, false)) {
536                     debugFatal("Could not set signal type to PeriodSignalling");
537                     return false;
538                 }
539                
540                 // buffertype and datatype are dependant on the API
541                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
542                 // buffertype and datatype are dependant on the API
543                 if(!(*it)->setBufferType(Port::E_RingBuffer)) {
544                     debugFatal("Could not set buffer type");
545                     return false;
546                 }
547                 if(!(*it)->setDataType(Port::E_MidiEvent)) {
548                     debugFatal("Could not set data type");
549                     return false;
550                 }
551                 break;
552             default:
553                 debugWarning("Unsupported port type specified\n");
554                 break;
555         }
556     }
557
558     // the API specific settings of the ports should already be set,
559     // as this is called from the processorManager->prepare()
560     // so we can init the ports
561     if(!initPorts()) {
562         debugFatal("Could not initialize ports!\n");
563         return false;
564     }
565
566     if(!preparePorts()) {
567         debugFatal("Could not initialize ports!\n");
568         return false;
569     }
570
571     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n");
572     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, FDF: %d, DBS: %d, SYT: %d\n",
573              m_framerate,m_fdf,m_dimension,m_syt_interval);
574     debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n",
575              m_period,m_nb_buffers);
576     debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n",
577              m_port,m_channel);
578
579     return true;
580
581 }
582
583 bool AmdtpTransmitStreamProcessor::prepareForStart() {
584
585     return true;
586 }
587
588 bool AmdtpTransmitStreamProcessor::prepareForStop() {
589     disable();
590     return true;
591 }
592
593 bool AmdtpTransmitStreamProcessor::prepareForEnable() {
594
595     debugOutput(DEBUG_LEVEL_VERBOSE,"Preparing to enable...\n");
596
597     if (!StreamProcessor::prepareForEnable()) {
598         debugError("StreamProcessor::prepareForEnable failed\n");
599         return false;
600     }
601
602     return true;
603 }
604
605 bool AmdtpTransmitStreamProcessor::transferSilence(unsigned int nframes) {
606     bool retval;
607    
608     char *dummybuffer=(char *)calloc(sizeof(quadlet_t),nframes*m_dimension);
609    
610     transmitSilenceBlock(dummybuffer, nframes, 0);
611
612     // add the silence data to the ringbuffer
613     if(m_data_buffer->writeFrames(nframes, dummybuffer, 0)) {
614         retval=true;
615     } else {
616         debugWarning("Could not write to event buffer\n");
617         retval=false;
618     }
619
620     free(dummybuffer);
621    
622     return retval;
623 }
624
625 bool AmdtpTransmitStreamProcessor::canClientTransferFrames(unsigned int nbframes) {
626     // there has to be enough space to put the frames in
627     return m_ringbuffer_size_frames - m_data_buffer->getFrameCounter() > nbframes;
628 }
629
630 bool AmdtpTransmitStreamProcessor::putFrames(unsigned int nbframes, int64_t ts) {
631     m_PeriodStat.mark(m_data_buffer->getBufferFill());
632    
633     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "AmdtpTransmitStreamProcessor::putFrames(%d, %llu)\n", nbframes, ts);
634    
635     // The timestamp passed to this function is the time
636     // of the period transfer. This means that we have to
637     // add our max buffer size to it to ensure causality
638     // in all cases:
639     // we have to make sure that the buffer HEAD timestamp
640     // lies in the future for every possible buffer fill case.
641     float ticks_per_frame=m_SyncSource->getTicksPerFrame();
642     ts = addTicks(ts,(uint32_t)((float)m_ringbuffer_size_frames * ticks_per_frame));
643    
644     // transfer the data
645     m_data_buffer->blockProcessWriteFrames(nbframes, ts);
646
647     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " New timestamp: %llu\n", ts);
648
649     return true;
650 }
651 /*
652  * write received events to the stream ringbuffers.
653  */
654
655 bool AmdtpTransmitStreamProcessor::processWriteBlock(char *data,
656                        unsigned int nevents, unsigned int offset)
657 {
658     bool no_problem=true;
659
660     for ( PortVectorIterator it = m_PeriodPorts.begin();
661           it != m_PeriodPorts.end();
662           ++it )
663     {
664
665         if((*it)->isDisabled()) {continue;};
666        
667         //FIXME: make this into a static_cast when not DEBUG?
668
669         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
670         assert(pinfo); // this should not fail!!
671
672         switch(pinfo->getFormat()) {
673         case AmdtpPortInfo::E_MBLA:
674             if(encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
675                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
676                 no_problem=false;
677             }
678             break;
679         case AmdtpPortInfo::E_SPDIF: // still unimplemented
680             break;
681         default: // ignore
682             break;
683         }
684     }
685     return no_problem;
686
687 }
688
689 int AmdtpTransmitStreamProcessor::transmitSilenceBlock(char *data,
690                        unsigned int nevents, unsigned int offset)
691 {
692     int problem=0;
693
694     for ( PortVectorIterator it = m_PeriodPorts.begin();
695           it != m_PeriodPorts.end();
696           ++it )
697     {
698
699         //FIXME: make this into a static_cast when not DEBUG?
700
701         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
702         assert(pinfo); // this should not fail!!
703
704         switch(pinfo->getFormat()) {
705         case AmdtpPortInfo::E_MBLA:
706             if(encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
707                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
708                 problem=1;
709             }
710             break;
711         case AmdtpPortInfo::E_SPDIF: // still unimplemented
712             break;
713         default: // ignore
714             break;
715         }
716     }
717     return problem;
718
719 }
720
721 /**
722  * @brief decode a packet for the packet-based ports
723  *
724  * @param data Packet data
725  * @param nevents number of events in data (including events of other ports & port types)
726  * @param dbc DataBlockCount value for this packet
727  * @return true if all successfull
728  */
729 bool AmdtpTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
730 {
731     bool ok=true;
732     char byte;
733    
734     quadlet_t *target_event=NULL;
735     unsigned int j;
736    
737     for ( PortVectorIterator it = m_PacketPorts.begin();
738           it != m_PacketPorts.end();
739           ++it )
740     {
741
742 #ifdef DEBUG
743         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
744         assert(pinfo); // this should not fail!!
745
746         // the only packet type of events for AMDTP is MIDI in mbla
747         assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi);
748 #endif
749        
750         AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it);
751        
752         // we encode this directly (no function call) due to the high frequency
753         /* idea:
754         spec says: current_midi_port=(dbc+j)%8;
755         => if we start at (dbc+stream->location-1)%8 [due to location_min=1],
756         we'll start at the right event for the midi port.
757         => if we increment j with 8, we stay at the right event.
758         */
759         // FIXME: as we know in advance how big a packet is (syt_interval) we can
760         //        predict how much loops will be present here
761         // first prefill the buffer with NO_DATA's on all time muxed channels
762        
763         for(j = (dbc & 0x07)+mp->getLocation()-1; j < nevents; j += 8) {
764        
765             target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition()));
766            
767             if(mp->canRead()) { // we can send a byte
768                 mp->readEvent(&byte);
769                 *target_event=htonl(
770                     IEC61883_AM824_SET_LABEL((byte)<<16,
771                                              IEC61883_AM824_LABEL_MIDI_1X));
772             } else {
773                 // can't send a byte, either because there is no byte,
774                 // or because this would exceed the maximum rate
775                 *target_event=htonl(
776                     IEC61883_AM824_SET_LABEL(0,IEC61883_AM824_LABEL_MIDI_NO_DATA));
777             }
778         }
779
780     }
781        
782     return ok;
783 }
784
785
786 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents(AmdtpAudioPort *p, quadlet_t *data,
787                        unsigned int offset, unsigned int nevents)
788 {
789     unsigned int j=0;
790
791     quadlet_t *target_event;
792
793     target_event=(quadlet_t *)(data + p->getPosition());
794
795     switch(p->getDataType()) {
796         default:
797         case Port::E_Int24:
798             {
799                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
800
801                 assert(nevents + offset <= p->getBufferSize());
802
803                 buffer+=offset;
804
805                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
806                     *target_event = htonl((*(buffer) & 0x00FFFFFF) | 0x40000000);
807                     buffer++;
808                     target_event += m_dimension;
809                 }
810             }
811             break;
812         case Port::E_Float:
813             {
814                 const float multiplier = (float)(0x7FFFFF00);
815                 float *buffer=(float *)(p->getBufferAddress());
816
817                 assert(nevents + offset <= p->getBufferSize());
818
819                 buffer+=offset;
820
821                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
822    
823                     // don't care for overflow
824                     float v = *buffer * multiplier;  // v: -231 .. 231
825                     unsigned int tmp = ((int)v);
826                     *target_event = htonl((tmp >> 8) | 0x40000000);
827                    
828                     buffer++;
829                     target_event += m_dimension;
830                 }
831             }
832             break;
833     }
834
835     return 0;
836 }
837 int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents(AmdtpAudioPort *p, quadlet_t *data,
838                        unsigned int offset, unsigned int nevents)
839 {
840     unsigned int j=0;
841
842     quadlet_t *target_event;
843
844     target_event=(quadlet_t *)(data + p->getPosition());
845
846     switch(p->getDataType()) {
847         default:
848         case Port::E_Int24:
849         case Port::E_Float:
850             {
851                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
852                     *target_event = htonl(0x40000000);
853                     target_event += m_dimension;
854                 }
855             }
856             break;
857     }
858
859     return 0;
860 }
861
862 /* --------------------- RECEIVE ----------------------- */
863
864 AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int port, int framerate, int dimension)
865     : ReceiveStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0), m_last_timestamp2(0) {
866
867 }
868
869 AmdtpReceiveStreamProcessor::~AmdtpReceiveStreamProcessor() {
870
871 }
872
873 bool AmdtpReceiveStreamProcessor::init() {
874
875     // call the parent init
876     // this has to be done before allocating the buffers,
877     // because this sets the buffersizes from the processormanager
878     if(!ReceiveStreamProcessor::init()) {
879         debugFatal("Could not do base class init (%d)\n",this);
880         return false;
881     }
882
883     return true;
884 }
885
886 enum raw1394_iso_disposition
887 AmdtpReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,
888                   unsigned char channel, unsigned char tag, unsigned char sy,
889                   unsigned int cycle, unsigned int dropped) {
890    
891     enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
892     m_last_cycle=cycle;
893    
894     struct iec61883_packet *packet = (struct iec61883_packet *) data;
895     assert(packet);
896
897 #ifdef DEBUG
898     if(dropped>0) {
899         debugWarning("Dropped %d packets on cycle %d\n",dropped, cycle);
900     }
901 #endif
902
903     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"ch%2u: CY=%4u, SYT=%08X (%4ucy + %04uticks) (running=%d, disabled=%d,%d)\n",
904         channel, cycle,ntohs(packet->syt), 
905         CYCLE_TIMER_GET_CYCLES(ntohs(packet->syt)), CYCLE_TIMER_GET_OFFSET(ntohs(packet->syt)),
906         m_running,m_disabled,m_is_disabled);
907
908     if((packet->syt != 0xFFFF)
909        && (packet->fdf != 0xFF)
910        && (packet->fmt == 0x10)
911        && (packet->dbs>0)
912        && (length>=2*sizeof(quadlet_t))) {
913        
914         unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
915
916         //=> store the previous timestamp
917         m_last_timestamp2=m_last_timestamp;
918
919         //=> convert the SYT to a full timestamp in ticks
920         m_last_timestamp=sytToFullTicks((uint32_t)ntohs(packet->syt),
921                                         cycle, m_handler->getCycleTimer());
922
923         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "RECV: CY=%04u TS=%011llu\n",
924                 cycle, m_last_timestamp);
925        
926         // we have to keep in mind that there are also
927         // some packets buffered by the ISO layer,
928         // at most x=m_handler->getWakeupInterval()
929         // these contain at most x*syt_interval
930         // frames, meaning that we might receive
931         // this packet x*syt_interval*ticks_per_frame
932         // later than expected (the real receive time)
933         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"STMP: %lluticks | buff=%d, syt_interval=%d, tpf=%f\n",
934             m_last_timestamp, m_handler->getWakeupInterval(),m_syt_interval,m_ticks_per_frame);
935        
936         m_last_timestamp += (uint64_t)(((float)m_handler->getWakeupInterval())
937                                        * ((float)m_syt_interval) * m_ticks_per_frame);
938         debugOutput(DEBUG_LEVEL_VERY_VERBOSE," ==> %lluticks\n", m_last_timestamp);
939        
940         // the receive processing delay indicates how much
941         // extra time we use as slack
942         m_last_timestamp += RECEIVE_PROCESSING_DELAY;
943        
944         // wrap if nescessary
945         m_last_timestamp=wrapAtMaxTicks(m_last_timestamp);
946        
947         //=> now estimate the device frame rate
948         if (m_last_timestamp2 && m_last_timestamp) {
949             // try and estimate the frame rate from the device
950            
951             // first get the measured difference between both
952             // timestamps
953             int64_t measured_difference;
954             measured_difference=((int64_t)(m_last_timestamp))
955                                -((int64_t)(m_last_timestamp2));
956             // correct for seconds wraparound
957             if (m_last_timestamp<m_last_timestamp2) {
958                 measured_difference+=128L*TICKS_PER_SECOND;
959             }
960
961             // implement a 1st order DLL to estimate the framerate
962             // this is the number of ticks between two samples
963             float f=measured_difference;
964             float err = f / (1.0*m_syt_interval) - m_ticks_per_frame;
965
966             // integrate the error
967             m_ticks_per_frame += RECEIVE_DLL_INTEGRATION_COEFFICIENT*err;
968            
969         }
970
971         //=> signal that we're running (if we are)
972         if(!m_running && nevents && m_last_timestamp2 && m_last_timestamp) {
973             debugOutput(DEBUG_LEVEL_VERBOSE,"Receive StreamProcessor %p started running at %d\n", this, cycle);
974             m_running=true;
975         }
976
977         //=> don't process the stream samples when it is not enabled.
978         if (!m_disabled && m_is_disabled) {
979             // this means that we are trying to enable
980             if (cycle == m_cycle_to_enable_at) {
981                 m_is_disabled=false;
982                 debugOutput(DEBUG_LEVEL_VERBOSE,"enabling StreamProcessor %p at %d\n", this, cycle);
983                 // the previous timestamp is the one we need to start with
984                 // because we're going to update the buffer again this loop
985                 // using writeframes
986                 m_data_buffer->setBufferTailTimestamp(m_last_timestamp2);
987
988             } else {
989                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
990                     "will enable StreamProcessor %p at %u, now is %d\n",
991                      this, m_cycle_to_enable_at, cycle);
992             }
993         } else if (m_disabled && !m_is_disabled) {
994             // trying to disable
995             debugOutput(DEBUG_LEVEL_VERBOSE,"disabling StreamProcessor %p at %u\n", this, cycle);
996             m_is_disabled=true;
997         }
998        
999         if(m_is_disabled) {
1000
1001             // we keep track of the timestamp here
1002             // this makes sure that we will have a somewhat accurate
1003             // estimate as to when a period might be ready. i.e. it will not
1004             // be ready earlier than this timestamp + period time
1005            
1006             // the next (possible) sample is not this one, but lies
1007             // SYT_INTERVAL * rate later
1008             uint64_t ts=m_last_timestamp+(uint64_t)((float)m_syt_interval * m_ticks_per_frame);
1009            
1010             // wrap if nescessary
1011             ts=wrapAtMaxTicks(ts);
1012
1013             // set the timestamp as if there will be a sample put into
1014             // the buffer by the next packet.
1015             m_data_buffer->setBufferTailTimestamp(ts);
1016            
1017             return RAW1394_ISO_DEFER;
1018         }
1019        
1020         //=> process the packet
1021         // add the data payload to the ringbuffer
1022         if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) {
1023             retval=RAW1394_ISO_OK;
1024            
1025             // process all ports that should be handled on a per-packet base
1026             // this is MIDI for AMDTP (due to the need of DBC)
1027             if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) {
1028                 debugWarning("Problem decoding Packet Ports\n");
1029                 retval=RAW1394_ISO_DEFER;
1030             }
1031            
1032         } else {
1033        
1034             debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",
1035                  cycle, m_data_buffer->getFrameCounter(), m_handler->getPacketCount());
1036            
1037             m_xruns++;
1038            
1039             // disable the processing, will be re-enabled when
1040             // the xrun is handled
1041             m_disabled=true;
1042             m_is_disabled=true;
1043
1044             retval=RAW1394_ISO_DEFER;
1045         }
1046     }
1047
1048     return retval;
1049 }
1050
1051 int64_t AmdtpReceiveStreamProcessor::getTimeUntilNextPeriodUsecs() {
1052     uint64_t time_at_period=getTimeAtPeriod();
1053    
1054     uint64_t cycle_timer=m_handler->getCycleTimerTicks();
1055    
1056     // calculate the time until the next period
1057     int64_t until_next=substractTicks(time_at_period,cycle_timer);
1058    
1059     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TAP=%11llu, CTR=%11llu, UTN=%11lld, TPUS=%f\n",
1060         time_at_period, cycle_timer, until_next, m_handler->getTicksPerUsec()
1061         );
1062    
1063     // now convert to usecs
1064     // don't use the mapping function because it only works
1065     // for absolute times, not the relative time we are
1066     // using here (which can also be negative).
1067     return (int64_t)(((float)until_next) / m_handler->getTicksPerUsec());
1068 }
1069
1070 uint64_t AmdtpReceiveStreamProcessor::getTimeAtPeriodUsecs() {
1071     // then we should convert this into usecs
1072     // FIXME: we assume that the TimeSource of the IsoHandler is
1073     //        in usecs.
1074     return m_handler->mapToTimeSource(getTimeAtPeriod());
1075 }
1076
1077 uint64_t AmdtpReceiveStreamProcessor::getTimeAtPeriod() {
1078
1079     // every time a packet is received both the framecounter and the base
1080     // timestamp are updated. This means that at any instance of time, the
1081     // front of the buffer (latest sample) timestamp is known.
1082     // As we know the number of frames in the buffer, and we now the rate
1083     // in ticks/frame, we can calculate the back of buffer timestamp as:
1084     //    back_of_buffer_time = front_time - nbframes * rate
1085     // the next period boundary time lies m_period frames later:
1086     //    next_period_boundary = back_of_buffer_time + m_period * rate
1087    
1088     // NOTE: we should account for the fact that the timestamp is not for
1089     //       the latest sample, but for the latest sample minus syt_interval-1
1090     //       because it is the timestamp for the first sample in the packet,
1091     //       while the complete packet contains SYT_INTERVAL samples.
1092     //       this makes the equation:
1093     //          back_of_buffer_time = front_time - (nbframes - (syt_interval - 1)) * rate
1094     //          next_period_boundary = back_of_buffer_time + m_period * rate
1095
1096     // NOTE: where do we add the processing delay?
1097     //       if we add it here:
1098     //          next_period_boundary += RECEIVE_PROCESSING_DELAY
1099    
1100     // the complete equation now is:
1101     // next_period_boundary = front_time - (nbframes - (syt_interval - 1)) * rate
1102     //                        + m_period * rate + RECEIVE_PROCESSING_DELAY
1103     // since syt_interval is a constant value, we can equally well ignore it, as
1104     // if it were already included in RECEIVE_PROCESSING_DELAY
1105     // making the equation (simplified:
1106     // next_period_boundary = front_time + (-nbframes + m_period) * rate
1107     //                        + RECEIVE_PROCESSING_DELAY
1108     // currently this is in ticks
1109    
1110     int64_t fc=m_data_buffer->getFrameCounter();
1111    
1112     int64_t next_period_boundary =  m_last_timestamp;
1113     next_period_boundary     += (int64_t)(((int64_t)m_period
1114                                           - fc) * m_ticks_per_frame);
1115    
1116     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD=%11lld, LTS=%11llu, FC=%5d, TPF=%f\n",
1117         next_period_boundary, m_last_timestamp, fc, m_ticks_per_frame
1118         );
1119        
1120     // next_period_boundary too large
1121     // happens if the timestamp wraps around while there are a lot of
1122     // frames in the buffer. We should add the wraparound value of the ticks
1123     // counter
1124    
1125     // next_period_boundary too small
1126     // happens when the last timestamp is near wrapping, and
1127     // m_framecounter is low.
1128     // this means: m_last_timestamp is near wrapping and have just had
1129     // a getPackets() from the client side. the projected next_period
1130     // boundary lies beyond the wrap value.
1131    
1132     // the action is to wrap the value.
1133     next_period_boundary=wrapAtMinMaxTicks(next_period_boundary);
1134    
1135     return next_period_boundary;
1136 }
1137
1138 void AmdtpReceiveStreamProcessor::dumpInfo()
1139 {
1140
1141     StreamProcessor::dumpInfo();
1142    
1143         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Device framerate  : %f\n", 24576000.0/m_ticks_per_frame);
1144
1145 }
1146
1147
1148 void AmdtpReceiveStreamProcessor::setVerboseLevel(int l) {
1149         setDebugLevel(l);
1150         ReceiveStreamProcessor::setVerboseLevel(l);
1151
1152 }
1153
1154 bool AmdtpReceiveStreamProcessor::reset() {
1155
1156     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
1157
1158     m_PeriodStat.reset();
1159     m_PacketStat.reset();
1160     m_WakeupStat.reset();
1161    
1162     // this needs to be reset to the nominal value
1163     // because xruns can cause the DLL value to shift a lot
1164     // making that we run into problems when trying to re-enable
1165     // streaming
1166     m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate);
1167
1168     // reset all non-device specific stuff
1169     // i.e. the iso stream and the associated ports
1170     if(!ReceiveStreamProcessor::reset()) {
1171             debugFatal("Could not do base class reset\n");
1172             return false;
1173     }
1174     return true;
1175 }
1176
1177 bool AmdtpReceiveStreamProcessor::prepare() {
1178
1179     m_PeriodStat.setName("RCV PERIOD");
1180     m_PacketStat.setName("RCV PACKET");
1181     m_WakeupStat.setName("RCV WAKEUP");
1182
1183         // prepare all non-device specific stuff
1184         // i.e. the iso stream and the associated ports
1185         if(!ReceiveStreamProcessor::prepare()) {
1186                 debugFatal("Could not prepare base class\n");
1187                 return false;
1188         }
1189        
1190         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
1191         switch (m_framerate) {
1192         case 32000:
1193                 m_syt_interval = 8;
1194                 break;
1195         case 44100:
1196                 m_syt_interval = 8;
1197                 break;
1198         default:
1199         case 48000:
1200                 m_syt_interval = 8;
1201                 break;
1202         case 88200:
1203                 m_syt_interval = 16;
1204                 break;
1205         case 96000:
1206                 m_syt_interval = 16;
1207                 break;
1208         case 176400:
1209                 m_syt_interval = 32;
1210                 break;
1211         case 192000:
1212                 m_syt_interval = 32;
1213                 break;
1214         }
1215
1216     // prepare the framerate estimate
1217     m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_framerate);
1218
1219     debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n",m_ticks_per_frame);
1220
1221     // allocate the event buffer
1222     unsigned int ringbuffer_size_frames=m_nb_buffers * m_period;
1223    
1224     // add the processing delay
1225     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding %u frames of SYT slack buffering...\n",
1226         (uint)(RECEIVE_PROCESSING_DELAY/m_ticks_per_frame));
1227     ringbuffer_size_frames+=(uint)(RECEIVE_PROCESSING_DELAY/m_ticks_per_frame);
1228    
1229     assert(m_data_buffer);   
1230     m_data_buffer->setBufferSize(ringbuffer_size_frames);
1231     m_data_buffer->setEventSize(sizeof(quadlet_t));
1232     m_data_buffer->setEventsPerFrame(m_dimension);
1233        
1234     // the buffer is written every syt_interval
1235     m_data_buffer->setUpdatePeriod(m_syt_interval);
1236     m_data_buffer->setNominalRate(m_ticks_per_frame);
1237    
1238     m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND);
1239    
1240     m_data_buffer->prepare();
1241
1242         // set the parameters of ports we can:
1243         // we want the audio ports to be period buffered,
1244         // and the midi ports to be packet buffered
1245         for ( PortVectorIterator it = m_Ports.begin();
1246                   it != m_Ports.end();
1247                   ++it )
1248         {
1249                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
1250                 if(!(*it)->setBufferSize(m_period)) {
1251                         debugFatal("Could not set buffer size to %d\n",m_period);
1252                         return false;
1253                 }
1254
1255                 switch ((*it)->getPortType()) {
1256                         case Port::E_Audio:
1257                                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
1258                                         debugFatal("Could not set signal type to PeriodSignalling");
1259                                         return false;
1260                                 }
1261                                 // buffertype and datatype are dependant on the API
1262                                 debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n");
1263                                 // buffertype and datatype are dependant on the API
1264                                 if(!(*it)->setBufferType(Port::E_PointerBuffer)) {
1265                                         debugFatal("Could not set buffer type");
1266                                         return false;
1267                                 }
1268                                 if(!(*it)->useExternalBuffer(true)) {
1269                                         debugFatal("Could not set external buffer usage");
1270                                         return false;
1271                                 }
1272                                 if(!(*it)->setDataType(Port::E_Float)) {
1273                                         debugFatal("Could not set data type");
1274                                         return false;
1275                                 }
1276                                 break;
1277                         case Port::E_Midi:
1278                                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
1279                                         debugFatal("Could not set signal type to PacketSignalling");
1280                                         return false;
1281                                 }
1282                                 // buffertype and datatype are dependant on the API
1283                                 // buffertype and datatype are dependant on the API
1284                                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
1285                                 // buffertype and datatype are dependant on the API
1286                                 if(!(*it)->setBufferType(Port::E_RingBuffer)) {
1287                                         debugFatal("Could not set buffer type");
1288                                         return false;
1289                                 }
1290                                 if(!(*it)->setDataType(Port::E_MidiEvent)) {
1291                                         debugFatal("Could not set data type");
1292                                         return false;
1293                                 }
1294                                 break;
1295                         default:
1296                                 debugWarning("Unsupported port type specified\n");
1297                                 break;
1298                 }
1299
1300         }
1301
1302         // the API specific settings of the ports should already be set,
1303         // as this is called from the processorManager->prepare()
1304         // so we can init the ports
1305         if(!initPorts()) {
1306                 debugFatal("Could not initialize ports!\n");
1307                 return false;
1308         }
1309
1310         if(!preparePorts()) {
1311                 debugFatal("Could not initialize ports!\n");
1312                 return false;
1313         }
1314
1315
1316         debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n");
1317         debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, DBS: %d, SYT: %d\n",
1318                      m_framerate,m_dimension,m_syt_interval);
1319         debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n",
1320                      m_period,m_nb_buffers);
1321         debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n",
1322                      m_port,m_channel);
1323         return true;
1324
1325 }
1326
1327 bool AmdtpReceiveStreamProcessor::prepareForStart() {
1328     disable();
1329     return true;
1330 }
1331
1332 bool AmdtpReceiveStreamProcessor::prepareForStop() {
1333     disable();
1334     return true;
1335 }
1336
1337 bool AmdtpReceiveStreamProcessor::canClientTransferFrames(unsigned int nbframes) {
1338     return m_data_buffer->getFrameCounter() >= (int) nbframes;
1339 }
1340
1341 bool AmdtpReceiveStreamProcessor::getFrames(unsigned int nbframes) {
1342
1343     m_PeriodStat.mark(m_data_buffer->getBufferFill());
1344
1345     // ask the buffer to process nbframes of frames
1346     // using it's registered client's processReadBlock(),
1347     // which should be ours
1348     m_data_buffer->blockProcessReadFrames(nbframes);
1349
1350     return true;
1351 }
1352
1353 /**
1354  * \brief write received events to the stream ringbuffers.
1355  */
1356 bool AmdtpReceiveStreamProcessor::processReadBlock(char *data,
1357                                            unsigned int nevents, unsigned int offset)
1358 {
1359         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "(%p)->processReadBlock(%u, %u)\n",this,nevents,offset);
1360        
1361         bool no_problem=true;
1362
1363         for ( PortVectorIterator it = m_PeriodPorts.begin();
1364           it != m_PeriodPorts.end();
1365           ++it )
1366     {
1367
1368         if((*it)->isDisabled()) {continue;};
1369
1370                 //FIXME: make this into a static_cast when not DEBUG?
1371
1372                 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
1373                 assert(pinfo); // this should not fail!!
1374
1375                 switch(pinfo->getFormat()) {
1376                 case AmdtpPortInfo::E_MBLA:
1377                         if(decodeMBLAEventsToPort(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
1378                                 debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str());
1379                                 no_problem=false;
1380                         }
1381                         break;
1382                 case AmdtpPortInfo::E_SPDIF: // still unimplemented
1383                         break;
1384         /* for this processor, midi is a packet based port
1385                 case AmdtpPortInfo::E_Midi:
1386                         break;*/
1387                 default: // ignore
1388                         break;
1389                 }
1390     }
1391     return no_problem;
1392
1393 }
1394
1395 /**
1396  * @brief decode a packet for the packet-based ports
1397  *
1398  * @param data Packet data
1399  * @param nevents number of events in data (including events of other ports & port types)
1400  * @param dbc DataBlockCount value for this packet
1401  * @return true if all successfull
1402  */
1403 bool AmdtpReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
1404 {
1405         bool ok=true;
1406        
1407         quadlet_t *target_event=NULL;
1408         unsigned int j;
1409        
1410         for ( PortVectorIterator it = m_PacketPorts.begin();
1411           it != m_PacketPorts.end();
1412           ++it )
1413         {
1414
1415 #ifdef DEBUG
1416                 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
1417                 assert(pinfo); // this should not fail!!
1418
1419                 // the only packet type of events for AMDTP is MIDI in mbla
1420                 assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi);
1421 #endif
1422                 AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it);
1423                
1424                 // we decode this directly (no function call) due to the high frequency
1425                 /* idea:
1426                 spec says: current_midi_port=(dbc+j)%8;
1427                 => if we start at (dbc+stream->location-1)%8 [due to location_min=1],
1428                 we'll start at the right event for the midi port.
1429                 => if we increment j with 8, we stay at the right event.
1430                 */
1431                 // FIXME: as we know in advance how big a packet is (syt_interval) we can
1432                 //        predict how much loops will be present here
1433                 for(j = (dbc & 0x07)+mp->getLocation()-1; j < nevents; j += 8) {
1434                         target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition()));
1435                         quadlet_t sample_int=ntohl(*target_event);
1436                         // FIXME: this assumes that 2X and 3X speed isn't used,
1437                         // because only the 1X slot is put into the ringbuffer
1438                         if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) {
1439                                 sample_int=(sample_int >> 16) & 0x000000FF;
1440                                 if(!mp->writeEvent(&sample_int)) {
1441                                         debugWarning("Packet port events lost\n");
1442                                         ok=false;
1443                                 }
1444                         }
1445                 }
1446
1447         }
1448        
1449         return ok;
1450 }
1451
1452 int AmdtpReceiveStreamProcessor::decodeMBLAEventsToPort(AmdtpAudioPort *p, quadlet_t *data,
1453                                            unsigned int offset, unsigned int nevents)
1454 {
1455         unsigned int j=0;
1456
1457 //      printf("****************\n");
1458 //      hexDumpQuadlets(data,m_dimension*4);
1459 //      printf("****************\n");
1460
1461         quadlet_t *target_event;
1462
1463         target_event=(quadlet_t *)(data + p->getPosition());
1464
1465         switch(p->getDataType()) {
1466                 default:
1467                 case Port::E_Int24:
1468                         {
1469                                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
1470
1471                                 assert(nevents + offset <= p->getBufferSize());
1472
1473                                 buffer+=offset;
1474
1475                                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
1476                                         *(buffer)=(ntohl((*target_event) ) & 0x00FFFFFF);
1477                                         buffer++;
1478                                         target_event+=m_dimension;
1479                                 }
1480                         }
1481                         break;
1482                 case Port::E_Float:
1483                         {
1484                                 const float multiplier = 1.0f / (float)(0x7FFFFF);
1485                                 float *buffer=(float *)(p->getBufferAddress());
1486
1487                                 assert(nevents + offset <= p->getBufferSize());
1488
1489                                 buffer+=offset;
1490
1491                                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
1492        
1493                                         unsigned int v = ntohl(*target_event) & 0x00FFFFFF;
1494                                         // sign-extend highest bit of 24-bit int
1495                                         int tmp = (int)(v << 8) / 256;
1496                
1497                                         *buffer = tmp * multiplier;
1498                                
1499                                         buffer++;
1500                                         target_event+=m_dimension;
1501                                 }
1502                         }
1503                         break;
1504         }
1505
1506         return 0;
1507 }
1508
1509 } // end of namespace FreebobStreaming
Note: See TracBrowser for help on using the browser.