root/branches/api-cleanup/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp

Revision 816, 21.6 kB (checked in by ppalmers, 14 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 Jonathan Woithe
3  * Copyright (C) 2005-2007 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "config.h"
26
27 #include "MotuTransmitStreamProcessor.h"
28 #include "MotuPort.h"
29 #include "../StreamProcessorManager.h"
30 #include "devicemanager.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 // Set to 1 to enable the generation of a 1 kHz test tone in analog output 1
40 #define TESTTONE 1
41
42 #if TESTTONE
43 #include <math.h>
44 #endif
45
46 namespace Streaming
47 {
48
49 // A macro to extract specific bits from a native endian quadlet
50 #define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1))
51
52 // Convert a full timestamp into an SPH timestamp as required by the MOTU
53 static inline uint32_t fullTicksToSph(int64_t timestamp) {
54     return TICKS_TO_CYCLE_TIMER(timestamp) & 0x1ffffff;
55 }
56
57 /* transmit */
58 MotuTransmitStreamProcessor::MotuTransmitStreamProcessor(FFADODevice &parent, unsigned int event_size )
59         : StreamProcessor(parent, ePT_Transmit )
60         , m_event_size( event_size )
61         , m_tx_dbc( 0 )
62 {}
63
64 unsigned int
65 MotuTransmitStreamProcessor::getMaxPacketSize() {
66     int framerate = m_Parent.getDeviceManager().getStreamProcessorManager().getNominalRate();
67     return framerate<=48000?616:(framerate<=96000?1032:1160);
68 }
69
70 unsigned int
71 MotuTransmitStreamProcessor::getNominalFramesPerPacket() {
72     int framerate = m_Parent.getDeviceManager().getStreamProcessorManager().getNominalRate();
73     return framerate<=48000?8:(framerate<=96000?16:32);
74 }
75
76 enum StreamProcessor::eChildReturnValue
77 MotuTransmitStreamProcessor::generatePacketHeader (
78     unsigned char *data, unsigned int *length,
79     unsigned char *tag, unsigned char *sy,
80     int cycle, unsigned int dropped, unsigned int max_length )
81 {
82     // The number of events per packet expected by the MOTU is solely
83     // dependent on the current sample rate.  An 'event' is one sample from
84     // all channels plus possibly other midi and control data.
85     signed n_events = getNominalFramesPerPacket();
86
87     // Do housekeeping expected for all packets sent to the MOTU, even
88     // for packets containing no audio data.
89     *sy = 0x00;
90     *tag = 1;      // All MOTU packets have a CIP-like header
91     *length = n_events*m_event_size + 8;
92
93     signed int fc;
94     uint64_t presentation_time;
95     unsigned int presentation_cycle;
96     int cycles_until_presentation;
97
98     uint64_t transmit_at_time;
99     unsigned int transmit_at_cycle;
100     int cycles_until_transmit;
101
102     // FIXME: should become a define
103     // the absolute minimum number of cycles we want to transmit
104     // a packet ahead of the presentation time. The nominal time
105     // the packet is transmitted ahead of the presentation time is
106     // given by MOTU_TRANSMIT_TRANSFER_DELAY (in ticks), but in case we
107     // are too late for that, this constant defines how late we can
108     // be.
109     const int min_cycles_before_presentation = 1;
110     // FIXME: should become a define
111     // the absolute maximum number of cycles we want to transmit
112     // a packet ahead of the ideal transmit time. The nominal time
113     // the packet is transmitted ahead of the presentation time is
114     // given by MOTU_TRANSMIT_TRANSFER_DELAY (in ticks), but we can send
115     // packets early if we want to. (not completely according to spec)
116     const int max_cycles_to_transmit_early = 2;
117
118     debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "Try for cycle %d\n", cycle );
119     // check whether the packet buffer has packets for us to send.
120     // the base timestamp is the one of the next sample in the buffer
121     ffado_timestamp_t ts_head_tmp;
122     m_data_buffer->getBufferHeadTimestamp ( &ts_head_tmp, &fc ); // thread safe
123
124     // the timestamp gives us the time at which we want the sample block
125     // to be output by the device
126     presentation_time = ( uint64_t ) ts_head_tmp;
127     m_last_timestamp = presentation_time;
128
129     // now we calculate the time when we have to transmit the sample block
130     transmit_at_time = substractTicks ( presentation_time, MOTU_TRANSMIT_TRANSFER_DELAY );
131
132     // calculate the cycle this block should be presented in
133     // (this is just a virtual calculation since at that time it should
134     //  already be in the device's buffer)
135     presentation_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( presentation_time ) );
136
137     // calculate the cycle this block should be transmitted in
138     transmit_at_cycle = ( unsigned int ) ( TICKS_TO_CYCLES ( transmit_at_time ) );
139
140     // we can check whether this cycle is within the 'window' we have
141     // to send this packet.
142     // first calculate the number of cycles left before presentation time
143     cycles_until_presentation = diffCycles ( presentation_cycle, cycle );
144
145     // we can check whether this cycle is within the 'window' we have
146     // to send this packet.
147     // first calculate the number of cycles left before presentation time
148     cycles_until_transmit = diffCycles ( transmit_at_cycle, cycle );
149
150     if (dropped) {
151         debugOutput ( DEBUG_LEVEL_VERBOSE,
152                     "Gen HDR: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
153                     cycle,
154                     transmit_at_cycle, cycles_until_transmit,
155                     transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
156                     presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
157     }
158     // two different options:
159     // 1) there are not enough frames for one packet
160     //      => determine wether this is a problem, since we might still
161     //         have some time to send it
162     // 2) there are enough packets
163     //      => determine whether we have to send them in this packet
164     if ( fc < ( signed int ) getNominalFramesPerPacket() )
165     {
166         // not enough frames in the buffer,
167
168         // we can still postpone the queueing of the packets
169         // if we are far enough ahead of the presentation time
170         if ( cycles_until_presentation <= min_cycles_before_presentation )
171         {
172             debugOutput ( DEBUG_LEVEL_VERBOSE,
173                         "Insufficient frames (P): N=%02d, CY=%04u, TC=%04u, CUT=%04d\n",
174                         fc, cycle, transmit_at_cycle, cycles_until_transmit );
175             // we are too late
176             return eCRV_XRun;
177         }
178         else
179         {
180             debugOutput ( DEBUG_LEVEL_VERY_VERBOSE,
181                         "Insufficient frames (NP): N=%02d, CY=%04u, TC=%04u, CUT=%04d\n",
182                         fc, cycle, transmit_at_cycle, cycles_until_transmit );
183             // there is still time left to send the packet
184             // we want the system to give this packet another go at a later time instant
185             return eCRV_Again;
186         }
187     }
188     else
189     {
190         // there are enough frames, so check the time they are intended for
191         // all frames have a certain 'time window' in which they can be sent
192         // this corresponds to the range of the timestamp mechanism:
193         // we can send a packet 15 cycles in advance of the 'presentation time'
194         // in theory we can send the packet up till one cycle before the presentation time,
195         // however this is not very smart.
196
197         // There are 3 options:
198         // 1) the frame block is too early
199         //      => send an empty packet
200         // 2) the frame block is within the window
201         //      => send it
202         // 3) the frame block is too late
203         //      => discard (and raise xrun?)
204         //         get next block of frames and repeat
205
206         if(cycles_until_transmit < 0)
207         {
208             // we are too late
209             debugOutput(DEBUG_LEVEL_VERBOSE,
210                         "Too late: CY=%04u, TC=%04u, CUT=%04d, TSP=%011llu (%04u)\n",
211                         cycle,
212                         transmit_at_cycle, cycles_until_transmit,
213                         presentation_time, (unsigned int)TICKS_TO_CYCLES(presentation_time) );
214
215             // however, if we can send this sufficiently before the presentation
216             // time, it could be harmless.
217             // NOTE: dangerous since the device has no way of reporting that it didn't get
218             //       this packet on time.
219             if(cycles_until_presentation >= min_cycles_before_presentation)
220             {
221                 // we are not that late and can still try to transmit the packet
222                 m_tx_dbc += fillDataPacketHeader((quadlet_t *)data, length, m_last_timestamp);
223                 if (m_tx_dbc > 0xff)
224                     m_tx_dbc -= 0x100;
225                 return eCRV_Packet;
226             }
227             else   // definitely too late
228             {
229                 return eCRV_XRun;
230             }
231         }
232         else if(cycles_until_transmit <= max_cycles_to_transmit_early)
233         {
234             // it's time send the packet
235             m_tx_dbc += fillDataPacketHeader((quadlet_t *)data, length, m_last_timestamp);
236             if (m_tx_dbc > 0xff)
237                 m_tx_dbc -= 0x100;
238             return eCRV_Packet;
239         }
240         else
241         {
242             debugOutput ( DEBUG_LEVEL_VERY_VERBOSE,
243                         "Too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
244                         cycle,
245                         transmit_at_cycle, cycles_until_transmit,
246                         transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
247                         presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
248 #ifdef DEBUG
249             if ( cycles_until_transmit > max_cycles_to_transmit_early + 1 )
250             {
251                 debugOutput ( DEBUG_LEVEL_VERY_VERBOSE,
252                             "Way too early: CY=%04u, TC=%04u, CUT=%04d, TST=%011llu (%04u), TSP=%011llu (%04u)\n",
253                             cycle,
254                             transmit_at_cycle, cycles_until_transmit,
255                             transmit_at_time, ( unsigned int ) TICKS_TO_CYCLES ( transmit_at_time ),
256                             presentation_time, ( unsigned int ) TICKS_TO_CYCLES ( presentation_time ) );
257             }
258 #endif
259             // we are too early, send only an empty packet
260             return eCRV_EmptyPacket;
261         }
262     }
263     return eCRV_Invalid;
264 }
265
266 enum StreamProcessor::eChildReturnValue
267 MotuTransmitStreamProcessor::generatePacketData (
268     unsigned char *data, unsigned int *length,
269     unsigned char *tag, unsigned char *sy,
270     int cycle, unsigned int dropped, unsigned int max_length )
271 {
272     quadlet_t *quadlet = (quadlet_t *)data;
273     quadlet += 2; // skip the header
274     // Size of a single data frame in quadlets
275     unsigned dbs = m_event_size / 4;
276
277     // The number of events per packet expected by the MOTU is solely
278     // dependent on the current sample rate.  An 'event' is one sample from
279     // all channels plus possibly other midi and control data.
280     signed n_events = getNominalFramesPerPacket();
281
282     if (m_data_buffer->readFrames(n_events, (char *)(data + 8))) {
283         float ticks_per_frame = m_Parent.getDeviceManager().getStreamProcessorManager().getSyncSource().getActualRate();
284
285 #if TESTTONE
286         // FIXME: remove this hacked in 1 kHz test signal to
287         // analog-1 when testing is complete.
288         signed int i, int_tpf = (int)ticks_per_frame;
289         unsigned char *sample = data+8+16;
290         for (i=0; i<n_events; i++, sample+=m_event_size) {
291             static signed int a_cx = 0;
292             // Each sample is 3 bytes with MSB in lowest address (ie:
293             // network byte order).  After byte order swap, the 24-bit
294             // MSB is in the second byte of val.
295             signed int val = htonl((int)(0x7fffff*sin((1000.0*2.0*M_PI/24576000.0)*a_cx)));
296             memcpy(sample,((char *)&val)+1,3);
297             if ((a_cx+=int_tpf) >= 24576000) {
298                 a_cx -= 24576000;
299             }
300         }
301 #endif
302
303         // Set up each frames's SPH.
304         for (int i=0; i < n_events; i++, quadlet += dbs) {
305 //FIXME: not sure which is best for the MOTU
306 //            int64_t ts_frame = addTicks(ts, (unsigned int)(i * ticks_per_frame));
307             int64_t ts_frame = addTicks(m_last_timestamp, (unsigned int)(i * ticks_per_frame));
308             *quadlet = htonl(fullTicksToSph(ts_frame));
309         }
310
311         return eCRV_OK;
312     }
313     else return eCRV_XRun;
314
315 }
316
317 enum StreamProcessor::eChildReturnValue
318 MotuTransmitStreamProcessor::generateSilentPacketHeader (
319     unsigned char *data, unsigned int *length,
320     unsigned char *tag, unsigned char *sy,
321     int cycle, unsigned int dropped, unsigned int max_length )
322 {
323     debugOutput ( DEBUG_LEVEL_VERY_VERBOSE, "XMIT NONE: CY=%04u, TSP=%011llu (%04u)\n",
324                 cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) );
325
326     // Do housekeeping expected for all packets sent to the MOTU, even
327     // for packets containing no audio data.
328     *sy = 0x00;
329     *tag = 1;      // All MOTU packets have a CIP-like header
330     *length = 8;
331
332     m_tx_dbc += fillNoDataPacketHeader ( (quadlet_t *)data, length );
333     return eCRV_OK;
334 }
335
336 enum StreamProcessor::eChildReturnValue
337 MotuTransmitStreamProcessor::generateSilentPacketData (
338     unsigned char *data, unsigned int *length,
339     unsigned char *tag, unsigned char *sy,
340     int cycle, unsigned int dropped, unsigned int max_length )
341 {
342     return eCRV_OK; // no need to do anything
343 }
344
345 unsigned int MotuTransmitStreamProcessor::fillDataPacketHeader (
346     quadlet_t *data, unsigned int* length,
347     uint32_t ts )
348 {
349     quadlet_t *quadlet = (quadlet_t *)data;
350     // Size of a single data frame in quadlets
351     unsigned dbs = m_event_size / 4;
352
353     // The number of events per packet expected by the MOTU is solely
354     // dependent on the current sample rate.  An 'event' is one sample from
355     // all channels plus possibly other midi and control data.
356     signed n_events = getNominalFramesPerPacket();
357
358     // construct the packet CIP-like header.  Even if this is a data-less
359     // packet the dbs field is still set as if there were data blocks
360     // present.  For data-less packets the dbc is the same as the previously
361     // transmitted block.
362     *quadlet = htonl(0x00000400 | ((m_Parent.get1394Service().getLocalNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16));
363     quadlet++;
364     *quadlet = htonl(0x8222ffff);
365     quadlet++;
366     return n_events;
367 }
368
369 unsigned int MotuTransmitStreamProcessor::fillNoDataPacketHeader (
370     quadlet_t *data, unsigned int* length )
371 {
372     quadlet_t *quadlet = (quadlet_t *)data;
373     // Size of a single data frame in quadlets
374     unsigned dbs = m_event_size / 4;
375     // construct the packet CIP-like header.  Even if this is a data-less
376     // packet the dbs field is still set as if there were data blocks
377     // present.  For data-less packets the dbc is the same as the previously
378     // transmitted block.
379     *quadlet = htonl(0x00000400 | ((m_Parent.get1394Service().getLocalNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16));
380     quadlet++;
381     *quadlet = htonl(0x8222ffff);
382     quadlet++;
383     *length = 8;
384     return 0;
385 }
386
387 bool MotuTransmitStreamProcessor::prepareChild()
388 {
389     debugOutput ( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this );
390     return true;
391 }
392
393 /*
394 * compose the event streams for the packets from the port buffers
395 */
396 bool MotuTransmitStreamProcessor::processWriteBlock(char *data,
397                        unsigned int nevents, unsigned int offset) {
398     bool no_problem=true;
399     unsigned int i;
400
401     // FIXME: ensure the MIDI and control streams are all zeroed until
402     // such time as they are fully implemented.
403     for (i=0; i<nevents; i++) {
404         memset(data+4+i*m_event_size, 0x00, 6);
405     }
406
407     for ( PortVectorIterator it = m_Ports.begin();
408       it != m_Ports.end();
409       ++it ) {
410         // If this port is disabled, don't process it
411         if((*it)->isDisabled()) {continue;};
412
413         Port *port=(*it);
414
415         switch(port->getPortType()) {
416
417         case Port::E_Audio:
418             if (encodePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
419                 debugWarning("Could not encode port %s to Motu events",(*it)->getName().c_str());
420                 no_problem=false;
421             }
422             break;
423         case Port::E_Midi:
424 //             if (encodePortToMotuMidiEvents(static_cast<MotuMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) {
425 //                 debugWarning("Could not encode port %s to Midi events",(*it)->getName().c_str());
426 //                 no_problem=false;
427 //             }
428             break;
429         default: // ignore
430             break;
431         }
432     }
433     return no_problem;
434 }
435
436 bool
437 MotuTransmitStreamProcessor::transmitSilenceBlock(char *data,
438                        unsigned int nevents, unsigned int offset) {
439     // This is the same as the non-silence version, except that is
440     // doesn't read from the port buffers.
441     bool no_problem = true;
442     for ( PortVectorIterator it = m_Ports.begin();
443       it != m_Ports.end();
444       ++it ) {
445         Port *port=(*it);
446
447         switch(port->getPortType()) {
448
449         case Port::E_Audio:
450             if (encodeSilencePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
451                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
452                 no_problem = false;
453             }
454             break;
455         case Port::E_Midi:
456 //             if (encodeSilencePortToMotuMidiEvents(static_cast<MotuMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) {
457 //                 debugWarning("Could not encode port %s to Midi events",(*it)->getName().c_str());
458 //                 no_problem = false;
459 //             }
460             break;
461         default: // ignore
462             break;
463         }
464     }
465     return no_problem;
466 }
467
468 int MotuTransmitStreamProcessor::encodePortToMotuEvents(MotuAudioPort *p, quadlet_t *data,
469                        unsigned int offset, unsigned int nevents) {
470 // Encodes nevents worth of data from the given port into the given buffer.  The
471 // format of the buffer is precisely that which will be sent to the MOTU.
472 // The basic idea:
473 //   iterate over the ports
474 //     * get port buffer address
475 //     * loop over events
476 //         - pick right sample in event based upon PortInfo
477 //         - convert sample from Port format (E_Int24, E_Float, ..) to MOTU
478 //           native format
479 //
480 // We include the ability to start the transfer from the given offset within
481 // the port (expressed in frames) so the 'efficient' transfer method can be
482 // utilised.
483
484     unsigned int j=0;
485
486     // Use char here since the target address won't necessarily be
487     // aligned; use of an unaligned quadlet_t may cause issues on certain
488     // architectures.  Besides, the target (data going directly to the MOTU)
489     // isn't structured in quadlets anyway; it mainly consists of packed
490     // 24-bit integers.
491     unsigned char *target;
492     target = (unsigned char *)data + p->getPosition();
493
494     switch(m_StreamProcessorManager.getAudioDataType()) {
495         default:
496         case StreamProcessorManager::eADT_Int24:
497             {
498                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
499
500                 assert(nevents + offset <= p->getBufferSize());
501
502                 // Offset is in frames, but each port is only a single
503                 // channel, so the number of frames is the same as the
504                 // number of quadlets to offset (assuming the port buffer
505                 // uses one quadlet per sample, which is the case currently).
506                 buffer+=offset;
507
508                 for(j = 0; j < nevents; j += 1) { // Decode nsamples
509                     *target = (*buffer >> 16) & 0xff;
510                     *(target+1) = (*buffer >> 8) & 0xff;
511                     *(target+2) = (*buffer) & 0xff;
512
513                     buffer++;
514                     target+=m_event_size;
515                 }
516             }
517             break;
518         case StreamProcessorManager::eADT_Float:
519             {
520                 const float multiplier = (float)(0x7FFFFF);
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                     unsigned int v = (int)(*buffer * multiplier);
529                     *target = (v >> 16) & 0xff;
530                     *(target+1) = (v >> 8) & 0xff;
531                     *(target+2) = v & 0xff;
532
533                     buffer++;
534                     target+=m_event_size;
535                 }
536             }
537             break;
538     }
539
540     return 0;
541 }
542
543 int MotuTransmitStreamProcessor::encodeSilencePortToMotuEvents(MotuAudioPort *p, quadlet_t *data,
544                        unsigned int offset, unsigned int nevents) {
545     unsigned int j=0;
546     unsigned char *target = (unsigned char *)data + p->getPosition();
547
548     switch (m_StreamProcessorManager.getAudioDataType()) {
549     default:
550         case StreamProcessorManager::eADT_Int24:
551         case StreamProcessorManager::eADT_Float:
552         for (j = 0; j < nevents; j++) {
553             *target = *(target+1) = *(target+2) = 0;
554             target += m_event_size;
555         }
556         break;
557     }
558
559     return 0;
560 }
561
562 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.