root/branches/libffado-2.0/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp

Revision 1448, 16.3 kB (checked in by ppalmers, 15 years ago)

increase midi reception verbose logging

Line 
1 /*
2  * Copyright (C) 2005-2008 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 2 of the License, or
12  * (at your option) version 3 of the License.
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 #include "config.h"
24
25 #include "AmdtpReceiveStreamProcessor.h"
26 #include "AmdtpPort.h"
27 #include "../StreamProcessorManager.h"
28 #include "devicemanager.h"
29
30 #include "libieee1394/ieee1394service.h"
31 #include "libieee1394/IsoHandlerManager.h"
32 #include "libieee1394/cycletimer.h"
33
34 #include "libutil/ByteSwap.h"
35 #include <assert.h>
36 #include "libutil/SystemTimeSource.h"
37
38 namespace Streaming {
39
40 /* --------------------- RECEIVE ----------------------- */
41
42 AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(FFADODevice &parent, int dimension)
43     : StreamProcessor(parent, ePT_Receive)
44     , m_dimension( dimension )
45     , m_nb_audio_ports( 0 )
46     , m_nb_midi_ports( 0 )
47
48 {}
49
50 unsigned int
51 AmdtpReceiveStreamProcessor::getSytInterval() {
52     switch (m_StreamProcessorManager.getNominalRate()) {
53         case 32000:
54         case 44100:
55         case 48000:
56             return 8;
57         case 88200:
58         case 96000:
59             return 16;
60         case 176400:
61         case 192000:
62             return 32;
63         default:
64             debugError("Unsupported rate: %d\n", m_StreamProcessorManager.getNominalRate());
65             return 0;
66     }
67 }
68
69 bool AmdtpReceiveStreamProcessor::prepareChild() {
70     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this);
71     m_syt_interval = getSytInterval();
72
73     if (!initPortCache()) {
74         debugError("Could not init port cache\n");
75         return false;
76     }
77
78     return true;
79 }
80
81
82 /**
83  * Processes packet header to extract timestamps and so on
84  * @param data
85  * @param length
86  * @param channel
87  * @param tag
88  * @param sy
89  * @param pkt_ctr CTR value when packet was received
90  * @return
91  */
92 enum StreamProcessor::eChildReturnValue
93 AmdtpReceiveStreamProcessor::processPacketHeader(unsigned char *data, unsigned int length,
94                                                  unsigned char tag, unsigned char sy,
95                                                  uint32_t pkt_ctr)
96 {
97     struct iec61883_packet *packet = (struct iec61883_packet *) data;
98     assert(packet);
99     bool ok = (packet->syt != 0xFFFF) &&
100               (packet->fdf != 0xFF) &&
101               (packet->fmt == 0x10) &&
102               (packet->dbs > 0) &&
103               (length >= 2*sizeof(quadlet_t));
104     if(ok) {
105         m_last_timestamp = sytRecvToFullTicks2((uint32_t)CondSwapFromBus16(packet->syt), pkt_ctr);
106         //#ifdef DEBUG
107         #if 0
108         uint32_t now = m_1394service.getCycleTimer();
109
110         //=> convert the SYT to a full timestamp in ticks
111         uint64_t old_last_timestamp = sytRecvToFullTicks((uint32_t)CondSwapFromBus16(packet->syt),
112                                               CYCLE_TIMER_GET_CYCLES(pkt_ctr), now);
113         if(m_last_timestamp != old_last_timestamp) {
114             debugWarning("discepancy between timestamp calculations\n");
115         }
116         #endif
117     }
118     return (ok ? eCRV_OK : eCRV_Invalid );
119 }
120
121 /**
122  * extract the data from the packet
123  * @pre the IEC61883 packet is valid according to isValidPacket
124  * @param data
125  * @param length
126  * @param channel
127  * @param tag
128  * @param sy
129  * @param pkt_ctr
130  * @return
131  */
132 enum StreamProcessor::eChildReturnValue
133 AmdtpReceiveStreamProcessor::processPacketData(unsigned char *data, unsigned int length) {
134     struct iec61883_packet *packet = (struct iec61883_packet *) data;
135     assert(packet);
136
137     unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
138
139     // we have to keep in mind that there are also
140     // some packets buffered by the ISO layer,
141     // at most x=m_handler->getWakeupInterval()
142     // these contain at most x*syt_interval
143     // frames, meaning that we might receive
144     // this packet x*syt_interval*ticks_per_frame
145     // later than expected (the real receive time)
146     #ifdef DEBUG
147     static int64_t last_t = Util::SystemTimeSource::getCurrentTime();
148     int64_t now_t = Util::SystemTimeSource::getCurrentTime();
149     if(isRunning()) {
150         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
151                            "STMP: %lluticks | syt_interval=%d, tpf=%f\n",
152                            m_last_timestamp, m_syt_interval, getTicksPerFrame());
153 /*        debugOutput(DEBUG_LEVEL_NORMAL,
154                            "STMP: %12llu ticks | delta_t: %5lld | bufferfill: %5d\n",
155                            m_last_timestamp, now_t-last_t, m_data_buffer->getBufferFill());*/
156     }
157     last_t = now_t;
158
159     // check whether nevents is a multiple of 8.
160     if (nevents & 0x7) {
161         debugError("Invalid nevents value for AMDTP (%u)\n", nevents);
162     }
163     #endif
164
165     if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) {
166         return eCRV_OK;
167     } else {
168         return eCRV_XRun;
169     }
170 }
171
172 /***********************************************
173  * Encoding/Decoding API                       *
174  ***********************************************/
175 /**
176  * @brief write received events to the stream ringbuffers.
177  */
178 bool AmdtpReceiveStreamProcessor::processReadBlock(char *data,
179                        unsigned int nevents, unsigned int offset)
180 {
181     debugOutputExtreme( DEBUG_LEVEL_VERY_VERBOSE,
182                         "(%p)->processReadBlock(%u, %u)\n",
183                         this,nevents,offset);
184
185     // update the variable parts of the cache
186     updatePortCache();
187
188     // decode audio data
189     switch(m_StreamProcessorManager.getAudioDataType()) {
190         case StreamProcessorManager::eADT_Int24:
191             decodeAudioPortsInt24((quadlet_t *)data, offset, nevents);
192             break;
193         case StreamProcessorManager::eADT_Float:
194             decodeAudioPortsFloat((quadlet_t *)data, offset, nevents);
195             break;
196     }
197
198     // do midi ports
199     decodeMidiPorts((quadlet_t *)data, offset, nevents);
200     return true;
201 }
202
203 //#ifdef __SSE2__
204 #if 0 // SSE code is not ready yet
205 #include <emmintrin.h>
206 #warning SSE2 build
207
208 /**
209  * @brief demux events to all audio ports (int24)
210  * @param data
211  * @param offset
212  * @param nevents
213  */
214 void
215 AmdtpReceiveStreamProcessor::decodeAudioPortsInt24(quadlet_t *data,
216                                                     unsigned int offset,
217                                                     unsigned int nevents)
218 {
219     unsigned int j;
220     quadlet_t *target_event;
221     unsigned int i;
222
223     for (i = 0; i < m_nb_audio_ports; i++) {
224         struct _MBLA_port_cache &p = m_audio_ports.at(i);
225         target_event = (quadlet_t *)(data + i);
226         assert(nevents + offset <= p.buffer_size );
227
228         if(p.buffer && p.enabled) {
229             quadlet_t *buffer = (quadlet_t *)(p.buffer);
230             buffer += offset;
231
232             for(j = 0; j < nevents; j += 1) {
233                 *(buffer)=(CondSwapFromBus32((*target_event) ) & 0x00FFFFFF);
234                 buffer++;
235                 target_event+=m_dimension;
236             }
237         }
238     }
239 }
240
241 /**
242  * @brief demux events to all audio ports (float)
243  * @param data
244  * @param offset
245  * @param nevents
246  */
247 void
248 AmdtpReceiveStreamProcessor::decodeAudioPortsFloat(quadlet_t *data,
249                                                     unsigned int offset,
250                                                     unsigned int nevents)
251 {
252     unsigned int j;
253     quadlet_t *target_event;
254     unsigned int i;
255     const float multiplier = 1.0f / (float)(0x7FFFFF);
256
257     for (i = 0; i < m_nb_audio_ports; i++) {
258         struct _MBLA_port_cache &p = m_audio_ports.at(i);
259         target_event = (quadlet_t *)(data + i);
260         assert(nevents + offset <= p.buffer_size );
261
262         if(p.buffer && p.enabled) {
263             float *buffer = (float *)(p.buffer);
264             buffer += offset;
265
266             for(j = 0; j < nevents; j += 1) {
267                 unsigned int v = CondSwapFromBus32(*target_event) & 0x00FFFFFF;
268                 // sign-extend highest bit of 24-bit int
269                 int tmp = (int)(v << 8) / 256;
270                 *buffer = tmp * multiplier;
271                 buffer++;
272                 target_event+=m_dimension;
273             }
274         }
275     }
276 }
277
278 #else
279 /**
280  * @brief demux events to all audio ports (int24)
281  * @param data
282  * @param offset
283  * @param nevents
284  */
285 void
286 AmdtpReceiveStreamProcessor::decodeAudioPortsInt24(quadlet_t *data,
287                                                     unsigned int offset,
288                                                     unsigned int nevents)
289 {
290     unsigned int j;
291     quadlet_t *target_event;
292     unsigned int i;
293
294     for (i = 0; i < m_nb_audio_ports; i++) {
295         struct _MBLA_port_cache &p = m_audio_ports.at(i);
296         target_event = (quadlet_t *)(data + i);
297         assert(nevents + offset <= p.buffer_size );
298
299         if(p.buffer && p.enabled) {
300             quadlet_t *buffer = (quadlet_t *)(p.buffer);
301             buffer += offset;
302
303             for(j = 0; j < nevents; j += 1) {
304                 *(buffer)=(CondSwapFromBus32((*target_event) ) & 0x00FFFFFF);
305                 buffer++;
306                 target_event+=m_dimension;
307             }
308         }
309     }
310 }
311
312 /**
313  * @brief demux events to all audio ports (float)
314  * @param data
315  * @param offset
316  * @param nevents
317  */
318 void
319 AmdtpReceiveStreamProcessor::decodeAudioPortsFloat(quadlet_t *data,
320                                                     unsigned int offset,
321                                                     unsigned int nevents)
322 {
323     unsigned int j;
324     quadlet_t *target_event;
325     unsigned int i;
326     const float multiplier = 1.0f / (float)(0x7FFFFF);
327
328     for (i = 0; i < m_nb_audio_ports; i++) {
329         struct _MBLA_port_cache &p = m_audio_ports.at(i);
330         target_event = (quadlet_t *)(data + i);
331         assert(nevents + offset <= p.buffer_size );
332
333         if(p.buffer && p.enabled) {
334             float *buffer = (float *)(p.buffer);
335             buffer += offset;
336
337             for(j = 0; j < nevents; j += 1) {
338                 unsigned int v = CondSwapFromBus32(*target_event) & 0x00FFFFFF;
339                 // sign-extend highest bit of 24-bit int
340                 int tmp = (int)(v << 8) / 256;
341                 *buffer = tmp * multiplier;
342                 buffer++;
343                 target_event+=m_dimension;
344             }
345         }
346     }
347 }
348
349 #endif
350
351 /**
352  * @brief decode all midi ports in the cache from events
353  * @param data
354  * @param offset
355  * @param nevents
356  */
357 void
358 AmdtpReceiveStreamProcessor::decodeMidiPorts(quadlet_t *data,
359                                               unsigned int offset,
360                                               unsigned int nevents)
361 {
362     quadlet_t *target_event;
363     quadlet_t sample_int;
364     unsigned int i,j;
365
366     for (i = 0; i < m_nb_midi_ports; i++) {
367         struct _MIDI_port_cache &p = m_midi_ports.at(i);
368         if (p.buffer && p.enabled) {
369             uint32_t *buffer = (quadlet_t *)(p.buffer);
370             buffer += offset;
371
372             for (j = p.location;j < nevents; j += 8) {
373                 target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position));
374                 sample_int=CondSwapFromBus32(*target_event);
375                 // FIXME: this assumes that 2X and 3X speed isn't used,
376                 // because only the 1X slot is put into the ringbuffer
377                 if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) {
378                     sample_int=(sample_int >> 16) & 0x000000FF;
379                     sample_int |= 0x01000000; // flag that there is a midi event present
380                     *buffer = sample_int;
381                     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Received midi byte %08X on port %p index %d\n", sample_int, p, j-p.location);
382                 } else {
383                     // make sure no event is received
384                     *buffer = 0;
385                 }
386                 buffer+=8;
387             }
388         }
389     }
390 }
391
392 bool
393 AmdtpReceiveStreamProcessor::initPortCache() {
394     // make use of the fact that audio ports are the first ports in
395     // the cluster as per AMDTP. so we can sort the ports by position
396     // and have very efficient lookups:
397     // m_float_ports.at(i).buffer -> audio stream i buffer
398     // for midi ports we simply cache all port info since they are (usually) not
399     // that numerous
400     m_nb_audio_ports = 0;
401     m_audio_ports.clear();
402    
403     m_nb_midi_ports = 0;
404     m_midi_ports.clear();
405    
406     for(PortVectorIterator it = m_Ports.begin();
407         it != m_Ports.end();
408         ++it )
409     {
410         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
411         assert(pinfo); // this should not fail!!
412
413         switch( pinfo->getFormat() )
414         {
415             case AmdtpPortInfo::E_MBLA:
416                 m_nb_audio_ports++;
417                 break;
418             case AmdtpPortInfo::E_SPDIF: // still unimplemented
419                 break;
420             case AmdtpPortInfo::E_Midi:
421                 m_nb_midi_ports++;
422                 break;
423             default: // ignore
424                 break;
425         }
426     }
427
428     unsigned int idx;
429     for (idx = 0; idx < m_nb_audio_ports; idx++) {
430         for(PortVectorIterator it = m_Ports.begin();
431             it != m_Ports.end();
432             ++it )
433         {
434             AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
435             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
436                         "idx %u: looking at port %s at position %u\n",
437                         idx, (*it)->getName().c_str(), pinfo->getPosition());
438             if(pinfo->getPosition() == idx) {
439                 struct _MBLA_port_cache p;
440                 p.port = dynamic_cast<AmdtpAudioPort *>(*it);
441                 if(p.port == NULL) {
442                     debugError("Port is not an AmdtpAudioPort!\n");
443                     return false;
444                 }
445                 p.buffer = NULL; // to be filled by updatePortCache
446                 #ifdef DEBUG
447                 p.buffer_size = (*it)->getBufferSize();
448                 #endif
449
450                 m_audio_ports.push_back(p);
451                 debugOutput(DEBUG_LEVEL_VERBOSE,
452                             "Cached port %s at position %u\n",
453                             p.port->getName().c_str(), idx);
454                 goto next_index;
455             }
456         }
457         debugError("No MBLA port found for position %d\n", idx);
458         return false;
459 next_index:
460         continue;
461     }
462
463     for(PortVectorIterator it = m_Ports.begin();
464         it != m_Ports.end();
465         ++it )
466     {
467         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
468         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
469                     "idx %u: looking at port %s at position %u, location %u\n",
470                     idx, (*it)->getName().c_str(), pinfo->getPosition(), pinfo->getLocation());
471         if ((*it)->getPortType() == Port::E_Midi) {
472             struct _MIDI_port_cache p;
473             p.port = dynamic_cast<AmdtpMidiPort *>(*it);
474             if(p.port == NULL) {
475                 debugError("Port is not an AmdtpMidiPort!\n");
476                 return false;
477             }
478             p.position = pinfo->getPosition();
479             p.location = pinfo->getLocation();
480             p.buffer = NULL; // to be filled by updatePortCache
481             #ifdef DEBUG
482             p.buffer_size = (*it)->getBufferSize();
483             #endif
484
485             m_midi_ports.push_back(p);
486             debugOutput(DEBUG_LEVEL_VERBOSE,
487                         "Cached port %s at position %u, location %u\n",
488                         p.port->getName().c_str(), p.position, p.location);
489         }
490     }
491
492     return true;
493 }
494
495 void
496 AmdtpReceiveStreamProcessor::updatePortCache() {
497     unsigned int idx;
498     for (idx = 0; idx < m_nb_audio_ports; idx++) {
499         struct _MBLA_port_cache& p = m_audio_ports.at(idx);
500         AmdtpAudioPort *port = p.port;
501         p.buffer = port->getBufferAddress();
502         p.enabled = !port->isDisabled();
503     }
504     for (idx = 0; idx < m_nb_midi_ports; idx++) {
505         struct _MIDI_port_cache& p = m_midi_ports.at(idx);
506         AmdtpMidiPort *port = p.port;
507         p.buffer = port->getBufferAddress();
508         p.enabled = !port->isDisabled();
509     }
510 }
511
512 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.