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

Revision 816, 26.9 kB (checked in by ppalmers, 16 years ago)

remove support for per-port datatypes. It's too much hassle and it doesn't add enough value.
It also prevents thorough performance optimizations, especially for larger channel counts (e.g. SSE based).

Audio ports are now either all float or all int24. This can be specified by the ffado_streaming_set_audio_datatype
API function before the streaming is prepared. Hence we can still support the direct conversion to the
clients datatype when demuxing the packets.

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 ( m_StreamProcessorManager.getAudioDataType() )
499     {
500         default:
501             debugError("bad type: %d\n", m_StreamProcessorManager.getAudioDataType());
502             return -1;
503         case StreamProcessorManager::eADT_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 StreamProcessorManager::eADT_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     quadlet_t *buffer = (quadlet_t *)(p->getBufferAddress());
558
559     assert(nevents + offset <= p->getBufferSize());
560
561     buffer+=offset;
562
563     for ( j = location; j < nevents; j += 8 )
564     {
565         target_event = (quadlet_t *) (data + ((j * m_dimension) + position));
566
567         if ( *buffer & 0xFF000000 )   // we can send a byte
568         {
569             tmpval = ((*buffer)<<16) & 0x00FF0000;
570             tmpval=IEC61883_AM824_SET_LABEL(tmpval, IEC61883_AM824_LABEL_MIDI_1X);
571             *target_event = htonl(tmpval);
572
573             // debugOutput ( DEBUG_LEVEL_VERBOSE, "MIDI port %s, pos=%u, loc=%u, nevents=%u, dim=%d\n",
574             //            p->getName().c_str(), position, location, nevents, m_dimension );
575             // debugOutput ( DEBUG_LEVEL_VERBOSE, "base=%p, target=%p, value=%08X\n",
576             //            data, target_event, tmpval );
577         } else {
578             // can't send a byte, either because there is no byte,
579             // or because this would exceed the maximum rate
580             // FIXME: this can be ifdef optimized since it's a constant
581             *target_event = htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA));
582         }
583         buffer+=8;
584     }
585
586     return 0;
587 }
588
589 int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data,
590         unsigned int offset, unsigned int nevents )
591 {
592     unsigned int j=0;
593
594     quadlet_t *target_event;
595
596     target_event= ( quadlet_t * ) ( data + p->getPosition() );
597
598     switch ( m_StreamProcessorManager.getAudioDataType() )
599     {
600         default:
601         case StreamProcessorManager::eADT_Int24:
602         case StreamProcessorManager::eADT_Float:
603         {
604             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples
605             {
606                 *target_event = htonl ( 0x40000000 );
607                 target_event += m_dimension;
608             }
609         }
610         break;
611     }
612
613     return 0;
614 }
615
616 int AmdtpTransmitStreamProcessor::encodeSilencePortToMidiEvents ( AmdtpMidiPort *p, quadlet_t *data,
617         unsigned int offset, unsigned int nevents )
618 {
619     unsigned int j=0;
620     unsigned int position = p->getPosition();
621     unsigned int location = p->getLocation();
622
623     quadlet_t *target_event;
624
625     for ( j = location; j < nevents; j += 8 )
626     {
627         target_event = (quadlet_t *) (data + ((j * m_dimension) + position));
628         *target_event=htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA));
629     }
630
631     return 0;
632 }
633
634 /**
635  * @brief encodes all audio ports in the cache to events
636  * @param data
637  * @param offset
638  * @param nevents
639  * @return
640  */
641 bool
642 AmdtpTransmitStreamProcessor::encodeAudioPorts(quadlet_t *data,
643                                                unsigned int offset,
644                                                unsigned int nevents)
645 {
646     unsigned int j=0;
647
648     quadlet_t *target_event;
649     unsigned int i;
650     for (i = 0; i < m_nb_audio_ports; i++) {
651         struct _MBLA_port_cache p = m_audio_ports.at(i);
652         target_event = (quadlet_t *)(data + i);
653         assert(nevents + offset <= p.buffer_size );
654
655         switch ( m_StreamProcessorManager.getAudioDataType() )
656         {
657             case StreamProcessorManager::eADT_Float:
658             {
659                 float *buffer = (float *)(p.buffer);
660                 buffer += offset;
661
662                 for (j = 0;j < nevents; j += 1)   // decode max nsamples
663                 {
664                     // don't care for overflow
665                     float v = (*buffer) * AMDTP_FLOAT_MULTIPLIER;
666                     unsigned int tmp = ((int) v);
667                     *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 );
668                     buffer++;
669                     target_event += m_dimension;
670                 }
671             }
672             break;
673             case StreamProcessorManager::eADT_Int24:
674             {
675                 uint32_t *buffer = (uint32_t *)(p.buffer);
676                 buffer += offset;
677
678                 for (j = 0; j < nevents; j += 1)   // decode max nsamples
679                 {
680                     *target_event = htonl(((*buffer) & 0x00FFFFFF) | 0x40000000);
681                     buffer++;
682                     target_event += m_dimension;
683                 }
684             }
685             break;
686             default:
687                 debugError("bad type: %d\n", m_StreamProcessorManager.getAudioDataType());
688                 return false;
689         }
690     }
691     return true;
692 }
693
694
695 bool
696 AmdtpTransmitStreamProcessor::initPortCache() {
697     // make use of the fact that audio ports are the first ports in
698     // the cluster as per AMDTP. so we can sort the ports by position
699     // and have very efficient lookups:
700     // m_float_ports.at(i).buffer -> audio stream i buffer
701     m_nb_audio_ports = 0;
702     m_audio_ports.clear();
703    
704     m_nb_midi_ports = 0;
705    
706     for(PortVectorIterator it = m_Ports.begin();
707         it != m_Ports.end();
708         ++it )
709     {
710         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
711         assert(pinfo); // this should not fail!!
712
713         switch( pinfo->getFormat() )
714         {
715             case AmdtpPortInfo::E_MBLA:
716                 m_nb_audio_ports++;
717                 break;
718             case AmdtpPortInfo::E_SPDIF: // still unimplemented
719                 break;
720             case AmdtpPortInfo::E_Midi:
721                 m_nb_midi_ports++;
722                 break;
723             default: // ignore
724                 break;
725         }
726     }
727
728     unsigned int idx;
729     for (idx = 0; idx < m_nb_audio_ports; idx++) {
730         for(PortVectorIterator it = m_Ports.begin();
731             it != m_Ports.end();
732             ++it )
733         {
734             AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
735             debugOutput(DEBUG_LEVEL_VERBOSE, "idx %u: looking at port %s at position %u\n",
736                                               idx, (*it)->getName().c_str(), pinfo->getPosition());
737             if(pinfo->getPosition() == idx) {
738                 struct _MBLA_port_cache p;
739                 p.port = dynamic_cast<AmdtpAudioPort *>(*it);
740                 if(p.port == NULL) {
741                     debugError("Port is not an AmdtpAudioPort!\n");
742                     return false;
743                 }
744 //                p.position = pinfo->getPosition();
745                 p.buffer = NULL; // to be filled by updatePortCache
746 #ifdef DEBUG
747                 p.buffer_size = (*it)->getBufferSize();
748 #endif
749
750                 m_audio_ports.push_back(p);
751                 debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u\n",
752                                                  p.port->getName().c_str(), idx);
753                 goto next_index;
754             }
755         }
756         debugError("No MBLA port found for position %d\n", idx);
757         return false;
758 next_index:
759         continue;
760     }
761
762     return true;
763 }
764
765 void
766 AmdtpTransmitStreamProcessor::updatePortCache() {
767     unsigned int idx;
768     for (idx = 0; idx < m_nb_audio_ports; idx++) {
769         AmdtpAudioPort *port = m_audio_ports.at(idx).port;
770         m_audio_ports.at(idx).buffer = port->getBufferAddress();
771     }
772 }
773
774 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.