root/branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp

Revision 815, 27.4 kB (checked in by ppalmers, 16 years ago)

- AMDTP transmit port caching for better performance
- less debug output in critical path

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25 #include "AmdtpTransmitStreamProcessor.h"
26 #include "AmdtpPort.h"
27 #include "../StreamProcessorManager.h"
28 #include "devicemanager.h"
29
30 #include "libutil/Time.h"
31
32 #include "libieee1394/ieee1394service.h"
33 #include "libieee1394/IsoHandlerManager.h"
34 #include "libieee1394/cycletimer.h"
35
36 #include <netinet/in.h>
37 #include <assert.h>
38
39 #define AMDTP_FLOAT_MULTIPLIER 2147483392.0
40
41 namespace Streaming
42 {
43
44 /* transmit */
45 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(FFADODevice &parent, int dimension)
46         : StreamProcessor(parent, ePT_Transmit)
47         , m_dimension( dimension )
48         , m_dbc( 0 )
49         , m_nb_audio_ports( 0 )
50         , m_nb_midi_ports( 0 )
51 {}
52
53 enum StreamProcessor::eChildReturnValue
54 AmdtpTransmitStreamProcessor::generatePacketHeader (
55     unsigned char *data, unsigned int *length,
56     unsigned char *tag, unsigned char *sy,
57     int cycle, unsigned int dropped, unsigned int max_length )
58 {
59     struct iec61883_packet *packet = ( struct iec61883_packet * ) data;
60     /* Our node ID can change after a bus reset, so it is best to fetch
61     * our node ID for each packet. */
62     packet->sid = m_1394service.getLocalNodeId() & 0x3f;
63
64     packet->dbs = m_dimension;
65     packet->fn = 0;
66     packet->qpc = 0;
67     packet->sph = 0;
68     packet->reserved = 0;
69     packet->dbc = m_dbc;
70     packet->eoh1 = 2;
71     packet->fmt = IEC61883_FMT_AMDTP;
72
73     *tag = IEC61883_TAG_WITH_CIP;
74     *sy = 0;
75
76     signed int fc;
77     uint64_t presentation_time;
78     unsigned int presentation_cycle;
79     int cycles_until_presentation;
80
81     uint64_t transmit_at_time;
82     unsigned int transmit_at_cycle;
83     int cycles_until_transmit;
84
85     debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "Try for cycle %d\n", cycle );
86     // check whether the packet buffer has packets for us to send.
87     // the base timestamp is the one of the next sample in the buffer
88     ffado_timestamp_t ts_head_tmp;
89     m_data_buffer->getBufferHeadTimestamp ( &ts_head_tmp, &fc ); // thread safe
90
91     // the timestamp gives us the time at which we want the sample block
92     // to be output by the device
93     presentation_time = ( uint64_t ) ts_head_tmp;
94     m_last_timestamp = presentation_time;
95
96     // now we calculate the time when we have to transmit the sample block
97     transmit_at_time = substractTicks ( presentation_time, AMDTP_TRANSMIT_TRANSFER_DELAY );
98
99     // calculate the cycle this block should be presented in
100     // (this is just a virtual calculation since at that time it should
101     //  already be in the device's buffer)
102     presentation_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( presentation_time ) );
103
104     // calculate the cycle this block should be transmitted in
105     transmit_at_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( transmit_at_time ) );
106
107     // we can check whether this cycle is within the 'window' we have
108     // to send this packet.
109     // first calculate the number of cycles left before presentation time
110     cycles_until_presentation = diffCycles ( presentation_cycle, cycle );
111
112     // we can check whether this cycle is within the 'window' we have
113     // to send this packet.
114     // first calculate the number of cycles left before presentation time
115     cycles_until_transmit = diffCycles ( transmit_at_cycle, cycle );
116
117     if (dropped) {
118         debugOutput ( DEBUG_LEVEL_VERBOSE,
119                     "Gen HDR: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
120                     cycle,
121                     transmit_at_cycle, cycles_until_transmit,
122                     transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
123                     presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
124     }
125     // two different options:
126     // 1) there are not enough frames for one packet
127     //      => determine wether this is a problem, since we might still
128     //         have some time to send it
129     // 2) there are enough packets
130     //      => determine whether we have to send them in this packet
131     if ( fc < ( signed int ) m_syt_interval )
132     {
133         // not enough frames in the buffer,
134
135         // we can still postpone the queueing of the packets
136         // if we are far enough ahead of the presentation time
137         if ( cycles_until_presentation <= AMDTP_MIN_CYCLES_BEFORE_PRESENTATION )
138         {
139             debugOutput ( DEBUG_LEVEL_VERBOSE,
140                         "Insufficient frames (P): N=%02d, CY=%04u, TC=%04u, CUT=%04d\n",
141                         fc, cycle, transmit_at_cycle, cycles_until_transmit );
142             // we are too late
143             return eCRV_XRun;
144         }
145         else
146         {
147             unsigned int now_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( m_1394service.getCycleTimerTicks() ) );
148
149             debugOutput ( DEBUG_LEVEL_VERBOSE,
150                         "Insufficient frames (NP): N=%02d, CY=%04u, TC=%04u, CUT=%04d, NOW=%04d\n",
151                         fc, cycle, transmit_at_cycle, cycles_until_transmit, now_cycle );
152             debugWarning("Insufficient frames (NP): N=%02d, CY=%04u, TC=%04u, CUT=%04d, NOW=%04d\n",
153                          fc, cycle, transmit_at_cycle, cycles_until_transmit, now_cycle );
154
155             // there is still time left to send the packet
156             // we want the system to give this packet another go at a later time instant
157             return eCRV_Again; // note that the raw1394 again system doesn't work as expected
158
159             // we could wait here for a certain time before trying again. However, this
160             // is not going to work since we then block the iterator thread, hence also
161             // the receiving code, meaning that we are not processing received packets,
162             // and hence there is no progression in the number of frames available.
163
164             // for example:
165             // SleepRelativeUsec(125); // one cycle
166             // goto try_block_of_frames;
167
168             // or more advanced, calculate how many cycles we are ahead of 'now' and
169             // base the sleep on that.
170
171             // note that this requires that there is one thread for each IsoHandler,
172             // otherwise we're in the deadlock described above.
173         }
174     }
175     else
176     {
177         // there are enough frames, so check the time they are intended for
178         // all frames have a certain 'time window' in which they can be sent
179         // this corresponds to the range of the timestamp mechanism:
180         // we can send a packet 15 cycles in advance of the 'presentation time'
181         // in theory we can send the packet up till one cycle before the presentation time,
182         // however this is not very smart.
183
184         // There are 3 options:
185         // 1) the frame block is too early
186         //      => send an empty packet
187         // 2) the frame block is within the window
188         //      => send it
189         // 3) the frame block is too late
190         //      => discard (and raise xrun?)
191         //         get next block of frames and repeat
192
193         if(cycles_until_transmit < 0)
194         {
195             // we are too late
196             debugOutput(DEBUG_LEVEL_VERBOSE,
197                         "Too late: CY=%04u, TC=%04u, CUT=%04d, TSP=%011llu (%04u)\n",
198                         cycle,
199                         transmit_at_cycle, cycles_until_transmit,
200                         presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time) );
201             //debugShowBackLogLines(200);
202 //             // however, if we can send this sufficiently before the presentation
203 //             // time, it could be harmless.
204 //             // NOTE: dangerous since the device has no way of reporting that it didn't get
205 //             //       this packet on time.
206 //             if(cycles_until_presentation >= AMDTP_MIN_CYCLES_BEFORE_PRESENTATION)
207 //             {
208 //                 // we are not that late and can still try to transmit the packet
209 //                 m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp);
210 //                 return (fc < (signed)(2*m_syt_interval) ? eCRV_Defer : eCRV_Packet);
211 //             }
212 //             else   // definitely too late
213 //             {
214                 return eCRV_XRun;
215 //             }
216         }
217         else if(cycles_until_transmit <= AMDTP_MAX_CYCLES_TO_TRANSMIT_EARLY)
218         {
219             // it's time send the packet
220             m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp);
221             return (fc < (signed)(2*m_syt_interval) ? eCRV_Defer : eCRV_Packet);
222         }
223         else
224         {
225             debugOutput ( DEBUG_LEVEL_VERY_VERBOSE,
226                         "Too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
227                         cycle,
228                         transmit_at_cycle, cycles_until_transmit,
229                         transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
230                         presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
231 #ifdef DEBUG
232             if ( cycles_until_transmit > AMDTP_MAX_CYCLES_TO_TRANSMIT_EARLY + 1 )
233             {
234                 debugOutput ( DEBUG_LEVEL_VERY_VERBOSE,
235                             "Way too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
236                             cycle,
237                             transmit_at_cycle, cycles_until_transmit,
238                             transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
239                             presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
240             }
241 #endif
242             // we are too early, send only an empty packet
243             return eCRV_EmptyPacket;
244         }
245     }
246     return eCRV_Invalid;
247 }
248
249 enum StreamProcessor::eChildReturnValue
250 AmdtpTransmitStreamProcessor::generatePacketData (
251     unsigned char *data, unsigned int *length,
252     unsigned char *tag, unsigned char *sy,
253     int cycle, unsigned int dropped, unsigned int max_length )
254 {
255     if ( m_data_buffer->readFrames ( m_syt_interval, ( char * ) ( data + 8 ) ) )
256     {
257         debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "XMIT DATA (cy %04d): TSP=%011llu (%04u)\n",
258                     cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) );
259         return eCRV_OK;
260     }
261     else return eCRV_XRun;
262
263 }
264
265 enum StreamProcessor::eChildReturnValue
266 AmdtpTransmitStreamProcessor::generateSilentPacketHeader (
267     unsigned char *data, unsigned int *length,
268     unsigned char *tag, unsigned char *sy,
269     int cycle, unsigned int dropped, unsigned int max_length )
270 {
271     struct iec61883_packet *packet = ( struct iec61883_packet * ) data;
272     debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "XMIT NONE (cy %04d): CY=%04u, TSP=%011llu (%04u)\n",
273                 cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) );
274
275     /* Our node ID can change after a bus reset, so it is best to fetch
276     * our node ID for each packet. */
277     packet->sid = m_1394service.getLocalNodeId() & 0x3f;
278
279     packet->dbs = m_dimension;
280     packet->fn = 0;
281     packet->qpc = 0;
282     packet->sph = 0;
283     packet->reserved = 0;
284     packet->dbc = m_dbc;
285     packet->eoh1 = 2;
286     packet->fmt = IEC61883_FMT_AMDTP;
287
288     *tag = IEC61883_TAG_WITH_CIP;
289     *sy = 0;
290
291     m_dbc += fillNoDataPacketHeader ( packet, length );
292     return eCRV_OK;
293 }
294
295 enum StreamProcessor::eChildReturnValue
296 AmdtpTransmitStreamProcessor::generateSilentPacketData (
297     unsigned char *data, unsigned int *length,
298     unsigned char *tag, unsigned char *sy,
299     int cycle, unsigned int dropped, unsigned int max_length )
300 {
301     return eCRV_OK; // no need to do anything
302 }
303
304 unsigned int AmdtpTransmitStreamProcessor::fillDataPacketHeader (
305     struct iec61883_packet *packet, unsigned int* length,
306     uint32_t ts )
307 {
308
309     packet->fdf = m_fdf;
310
311     // convert the timestamp to SYT format
312     uint16_t timestamp_SYT = TICKS_TO_SYT ( ts );
313     packet->syt = ntohs ( timestamp_SYT );
314
315     *length = m_syt_interval*sizeof ( quadlet_t ) *m_dimension + 8;
316
317     return m_syt_interval;
318 }
319
320 unsigned int AmdtpTransmitStreamProcessor::fillNoDataPacketHeader (
321     struct iec61883_packet *packet, unsigned int* length )
322 {
323
324     // no-data packets have syt=0xFFFF
325     // and have the usual amount of events as dummy data (?)
326     packet->fdf = IEC61883_FDF_NODATA;
327     packet->syt = 0xffff;
328
329     // FIXME: either make this a setting or choose
330     bool send_payload=true;
331     if ( send_payload )
332     {
333         // this means no-data packets with payload (DICE doesn't like that)
334         *length = 2*sizeof ( quadlet_t ) + m_syt_interval * m_dimension * sizeof ( quadlet_t );
335         return m_syt_interval;
336     }
337     else
338     {
339         // dbc is not incremented
340         // this means no-data packets without payload
341         *length = 2*sizeof ( quadlet_t );
342         return 0;
343     }
344 }
345
346 unsigned int
347 AmdtpTransmitStreamProcessor::getSytInterval() {
348     switch (m_StreamProcessorManager.getNominalRate()) {
349         case 32000:
350         case 44100:
351         case 48000:
352             return 8;
353         case 88200:
354         case 96000:
355             return 16;
356         case 176400:
357         case 192000:
358             return 32;
359         default:
360             debugError("Unsupported rate: %d\n", m_StreamProcessorManager.getNominalRate());
361             return 0;
362     }
363 }
364 unsigned int
365 AmdtpTransmitStreamProcessor::getFDF() {
366     switch (m_StreamProcessorManager.getNominalRate()) {
367         case 32000: return IEC61883_FDF_SFC_32KHZ;
368         case 44100: return IEC61883_FDF_SFC_44K1HZ;
369         case 48000: return IEC61883_FDF_SFC_48KHZ;
370         case 88200: return IEC61883_FDF_SFC_88K2HZ;
371         case 96000: return IEC61883_FDF_SFC_96KHZ;
372         case 176400: return IEC61883_FDF_SFC_176K4HZ;
373         case 192000: return IEC61883_FDF_SFC_192KHZ;
374         default:
375             debugError("Unsupported rate: %d\n", m_StreamProcessorManager.getNominalRate());
376             return 0;
377     }
378 }
379
380 bool AmdtpTransmitStreamProcessor::prepareChild()
381 {
382     debugOutput ( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this );
383     m_syt_interval = getSytInterval();
384     m_fdf = getFDF();
385
386     iec61883_cip_init (
387         &m_cip_status,
388         IEC61883_FMT_AMDTP,
389         m_fdf,
390         m_StreamProcessorManager.getNominalRate(),
391         m_dimension,
392         m_syt_interval );
393
394     if (!initPortCache()) {
395         debugError("Could not init port cache\n");
396         return false;
397     }
398
399     return true;
400 }
401
402 /*
403 * compose the event streams for the packets from the port buffers
404 */
405 bool AmdtpTransmitStreamProcessor::processWriteBlock ( char *data,
406         unsigned int nevents, unsigned int offset )
407 {
408     bool no_problem = true;
409     updatePortCache();
410
411     if(!encodeAudioPorts((quadlet_t *)data, offset, nevents)) {
412         debugError("Could not encode audio ports\n");
413         return false;
414     }
415
416 //     for ( PortVectorIterator it = m_Ports.begin();
417 //           it != m_Ports.end();
418 //           ++it )
419 //     {
420 //         if ( (*it)->isDisabled() ) { continue; };
421 //
422 //         //FIXME: make this into a static_cast when not DEBUG?
423 //         AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it );
424 //         assert ( pinfo ); // this should not fail!!
425 //
426 //         switch( pinfo->getFormat() )
427 //         {
428 //             case AmdtpPortInfo::E_MBLA:
429 //                 if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) )
430 //                 {
431 //                     debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() );
432 //                     no_problem = false;
433 //                 }
434 //                 break;
435 //             case AmdtpPortInfo::E_SPDIF: // still unimplemented
436 //                 break;
437 //             case AmdtpPortInfo::E_Midi:
438 //                 if( encodePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) )
439 //                 {
440 //                     debugWarning ( "Could not encode port %s to Midi events", (*it)->getName().c_str() );
441 //                     no_problem = false;
442 //                 }
443 //                 break;
444 //             default: // ignore
445 //                 break;
446 //         }
447 //     }
448     return no_problem;
449 }
450
451 bool
452 AmdtpTransmitStreamProcessor::transmitSilenceBlock(
453     char *data, unsigned int nevents, unsigned int offset)
454 {
455     bool no_problem = true;
456     for(PortVectorIterator it = m_Ports.begin();
457         it != m_Ports.end();
458         ++it )
459     {
460         //FIXME: make this into a static_cast when not DEBUG?
461         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
462         assert(pinfo); // this should not fail!!
463
464         switch( pinfo->getFormat() )
465         {
466             case AmdtpPortInfo::E_MBLA:
467                 if ( encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) )
468                 {
469                     debugWarning("Could not encode silence for port %s to MBLA events", (*it)->getName().c_str());
470                     no_problem = false;
471                 }
472                 break;
473             case AmdtpPortInfo::E_SPDIF: // still unimplemented
474                 break;
475             case AmdtpPortInfo::E_Midi:
476                 if( encodeSilencePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) )
477                 {
478                     debugWarning ( "Could not encode silence for port %s to Midi events", (*it)->getName().c_str() );
479                     no_problem = false;
480                 }
481                 break;
482             default: // ignore
483                 break;
484         }
485     }
486     return no_problem;
487 }
488
489 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data,
490         unsigned int offset, unsigned int nevents )
491 {
492     unsigned int j=0;
493
494     quadlet_t *target_event;
495
496     target_event= ( quadlet_t * ) ( data + p->getPosition() );
497
498     switch ( p->getDataType() )
499     {
500         default:
501             debugError("bad type: %d\n", p->getDataType());
502             return -1;
503         case Port::E_Int24:
504         {
505             quadlet_t *buffer= ( quadlet_t * ) ( p->getBufferAddress() );
506
507             assert ( nevents + offset <= p->getBufferSize() );
508
509             buffer+=offset;
510
511             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples
512             {
513                 *target_event = htonl ( ( * ( buffer ) & 0x00FFFFFF ) | 0x40000000 );
514                 buffer++;
515                 target_event += m_dimension;
516             }
517         }
518         break;
519         case Port::E_Float:
520         {
521             float *buffer= ( float * ) ( p->getBufferAddress() );
522
523             assert ( nevents + offset <= p->getBufferSize() );
524
525             buffer+=offset;
526
527             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples
528             {
529
530                 // don't care for overflow
531                 float v = *buffer * AMDTP_FLOAT_MULTIPLIER;  // v: -231 .. 231
532                 unsigned int tmp = ( ( int ) v );
533                 *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 );
534
535                 buffer++;
536                 target_event += m_dimension;
537             }
538         }
539         break;
540     }
541
542     return 0;
543 }
544
545 // note: make sure that the midi events in the port buffer are only placed on (buffer+offset+x)%8 == 0
546 // i.e. 8 frame aligned
547 int AmdtpTransmitStreamProcessor::encodePortToMidiEvents ( AmdtpMidiPort *p, quadlet_t *data,
548         unsigned int offset, unsigned int nevents )
549 {
550     unsigned int j=0;
551     unsigned int position = p->getPosition();
552     unsigned int location = p->getLocation();
553
554     quadlet_t *target_event;
555     quadlet_t tmpval;
556
557     switch ( p->getDataType() )
558     {
559         default:
560             debugError("bad type: %d\n", p->getDataType());
561             return -1;
562         case Port::E_MidiEvent:
563         {
564             quadlet_t *buffer = (quadlet_t *)(p->getBufferAddress());
565
566             assert(nevents + offset <= p->getBufferSize());
567
568             buffer+=offset;
569
570             for ( j = location; j < nevents; j += 8 )
571             {
572                 target_event = (quadlet_t *) (data + ((j * m_dimension) + position));
573
574                 if ( *buffer & 0xFF000000 )   // we can send a byte
575                 {
576                     tmpval = ((*buffer)<<16) & 0x00FF0000;
577                     tmpval=IEC61883_AM824_SET_LABEL(tmpval, IEC61883_AM824_LABEL_MIDI_1X);
578                     *target_event = htonl(tmpval);
579
580                     // debugOutput ( DEBUG_LEVEL_VERBOSE, "MIDI port %s, pos=%u, loc=%u, nevents=%u, dim=%d\n",
581                     //            p->getName().c_str(), position, location, nevents, m_dimension );
582                     // debugOutput ( DEBUG_LEVEL_VERBOSE, "base=%p, target=%p, value=%08X\n",
583                     //            data, target_event, tmpval );
584                 } else {
585                     // can't send a byte, either because there is no byte,
586                     // or because this would exceed the maximum rate
587                     // FIXME: this can be ifdef optimized since it's a constant
588                     *target_event = htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA));
589                 }
590                 buffer+=8;
591             }
592         }
593         break;
594     }
595     return 0;
596 }
597
598 int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data,
599         unsigned int offset, unsigned int nevents )
600 {
601     unsigned int j=0;
602
603     quadlet_t *target_event;
604
605     target_event= ( quadlet_t * ) ( data + p->getPosition() );
606
607     switch ( p->getDataType() )
608     {
609         default:
610         case Port::E_Int24:
611         case Port::E_Float:
612         {
613             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples
614             {
615                 *target_event = htonl ( 0x40000000 );
616                 target_event += m_dimension;
617             }
618         }
619         break;
620     }
621
622     return 0;
623 }
624
625 int AmdtpTransmitStreamProcessor::encodeSilencePortToMidiEvents ( AmdtpMidiPort *p, quadlet_t *data,
626         unsigned int offset, unsigned int nevents )
627 {
628     unsigned int j=0;
629     unsigned int position = p->getPosition();
630     unsigned int location = p->getLocation();
631
632     quadlet_t *target_event;
633
634     switch ( p->getDataType() )
635     {
636         default:
637             debugError("bad type: %d\n", p->getDataType());
638             return -1;
639         case Port::E_MidiEvent:
640         {
641             for ( j = location; j < nevents; j += 8 )
642             {
643                 target_event = (quadlet_t *) (data + ((j * m_dimension) + position));
644                 *target_event=htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA));
645             }
646         }
647         break;
648     }
649     return 0;
650 }
651
652 /**
653  * @brief encodes all audio ports in the cache to events
654  * @param data
655  * @param offset
656  * @param nevents
657  * @return
658  */
659 bool
660 AmdtpTransmitStreamProcessor::encodeAudioPorts(quadlet_t *data,
661                                                unsigned int offset,
662                                                unsigned int nevents)
663 {
664     unsigned int j=0;
665
666     quadlet_t *target_event;
667     unsigned int i;
668     for (i = 0; i < m_nb_audio_ports; i++) {
669         struct _MBLA_port_cache p = m_audio_ports.at(i);
670         target_event = (quadlet_t *)(data + i);
671         assert(nevents + offset <= p.buffer_size );
672
673         switch ( p.type )
674         {
675             case Port::E_Float:
676             {
677                 float *buffer = (float *)(p.buffer);
678                 buffer += offset;
679
680                 for (j = 0;j < nevents; j += 1)   // decode max nsamples
681                 {
682                     // don't care for overflow
683                     float v = (*buffer) * AMDTP_FLOAT_MULTIPLIER;
684                     unsigned int tmp = ((int) v);
685                     *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 );
686                     buffer++;
687                     target_event += m_dimension;
688                 }
689             }
690             break;
691             case Port::E_Int24:
692             {
693                 uint32_t *buffer = (uint32_t *)(p.buffer);
694                 buffer += offset;
695
696                 for (j = 0; j < nevents; j += 1)   // decode max nsamples
697                 {
698                     *target_event = htonl(((*buffer) & 0x00FFFFFF) | 0x40000000);
699                     buffer++;
700                     target_event += m_dimension;
701                 }
702             }
703             break;
704             default:
705                 debugError("bad type: %d\n", m_audio_ports.at(i).type);
706                 return false;
707         }
708     }
709     return true;
710 }
711
712
713 bool
714 AmdtpTransmitStreamProcessor::initPortCache() {
715     // make use of the fact that audio ports are the first ports in
716     // the cluster as per AMDTP. so we can sort the ports by position
717     // and have very efficient lookups:
718     // m_float_ports.at(i).buffer -> audio stream i buffer
719     m_nb_audio_ports = 0;
720     m_audio_ports.clear();
721    
722     m_nb_midi_ports = 0;
723    
724     for(PortVectorIterator it = m_Ports.begin();
725         it != m_Ports.end();
726         ++it )
727     {
728         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
729         assert(pinfo); // this should not fail!!
730
731         switch( pinfo->getFormat() )
732         {
733             case AmdtpPortInfo::E_MBLA:
734                 m_nb_audio_ports++;
735                 break;
736             case AmdtpPortInfo::E_SPDIF: // still unimplemented
737                 break;
738             case AmdtpPortInfo::E_Midi:
739                 m_nb_midi_ports++;
740                 break;
741             default: // ignore
742                 break;
743         }
744     }
745
746     unsigned int idx;
747     for (idx = 0; idx < m_nb_audio_ports; idx++) {
748         for(PortVectorIterator it = m_Ports.begin();
749             it != m_Ports.end();
750             ++it )
751         {
752             AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
753             debugOutput(DEBUG_LEVEL_VERBOSE, "idx %u: looking at port %s at position %u\n",
754                                               idx, (*it)->getName().c_str(), pinfo->getPosition());
755             if(pinfo->getPosition() == idx) {
756                 struct _MBLA_port_cache p;
757                 p.port = dynamic_cast<AmdtpAudioPort *>(*it);
758                 if(p.port == NULL) {
759                     debugError("Port is not an AmdtpAudioPort!\n");
760                     return false;
761                 }
762 //                p.position = pinfo->getPosition();
763                 p.buffer = NULL; // to be filled by updatePortCache
764                 p.type = (*it)->getDataType();
765 #ifdef DEBUG
766                 p.buffer_size = (*it)->getBufferSize();
767 #endif
768
769                 m_audio_ports.push_back(p);
770                 debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u\n",
771                                                  p.port->getName().c_str(), idx);
772                 goto next_index;
773             }
774         }
775         debugError("No MBLA port found for position %d\n", idx);
776         return false;
777 next_index:
778         continue;
779     }
780
781     return true;
782 }
783
784 void
785 AmdtpTransmitStreamProcessor::updatePortCache() {
786     unsigned int idx;
787     for (idx = 0; idx < m_nb_audio_ports; idx++) {
788         AmdtpAudioPort *port = m_audio_ports.at(idx).port;
789         m_audio_ports.at(idx).buffer = port->getBufferAddress();
790     }
791 }
792
793 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.