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

Revision 816, 10.9 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 "MotuReceiveStreamProcessor.h"
26 #include "MotuPort.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 <math.h>
35 #include <netinet/in.h>
36 #include <assert.h>
37
38 namespace Streaming {
39
40 // A macro to extract specific bits from a native endian quadlet
41 #define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1))
42
43 // Convert an SPH timestamp as received from the MOTU to a full timestamp in ticks.
44 static inline uint32_t sphRecvToFullTicks(uint32_t sph, uint32_t ct_now) {
45
46 uint32_t timestamp = CYCLE_TIMER_TO_TICKS(sph & 0x1ffffff);
47 uint32_t now_cycles = CYCLE_TIMER_GET_CYCLES(ct_now);
48
49 uint32_t ts_sec = CYCLE_TIMER_GET_SECS(ct_now);
50     // If the cycles have wrapped, correct ts_sec so it represents when timestamp
51     // was received.  The timestamps sent by the MOTU are always 1 or two cycles
52     // in advance of the cycle timer (reasons unknown at this stage).  In addition,
53     // iso buffering can delay the arrival of packets for quite a number of cycles
54     // (have seen a delay >12 cycles).
55     // Every so often we also see sph wrapping ahead of ct_now, so deal with that
56     // too.
57     if (CYCLE_TIMER_GET_CYCLES(sph) > now_cycles + 1000) {
58         if (ts_sec)
59             ts_sec--;
60         else
61             ts_sec = 127;
62     } else
63     if (now_cycles > CYCLE_TIMER_GET_CYCLES(sph) + 1000) {
64         if (ts_sec == 127)
65             ts_sec = 0;
66         else
67             ts_sec++;
68     }
69     return timestamp + ts_sec*TICKS_PER_SECOND;
70 }
71
72 MotuReceiveStreamProcessor::MotuReceiveStreamProcessor(FFADODevice &parent, unsigned int event_size)
73     : StreamProcessor(parent, ePT_Receive)
74     , m_event_size( event_size )
75 {}
76
77 unsigned int
78 MotuReceiveStreamProcessor::getMaxPacketSize() {
79     int framerate = m_Parent.getDeviceManager().getStreamProcessorManager().getNominalRate();
80     return framerate<=48000?616:(framerate<=96000?1032:1160);
81 }
82
83 unsigned int
84 MotuReceiveStreamProcessor::getNominalFramesPerPacket() {
85     int framerate = m_Parent.getDeviceManager().getStreamProcessorManager().getNominalRate();
86     return framerate<=48000?8:(framerate<=96000?16:32);
87 }
88
89 bool
90 MotuReceiveStreamProcessor::prepareChild() {
91     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this);
92
93     // prepare the framerate estimate
94     // FIXME: not needed anymore?
95     //m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_Parent.getDeviceManager().getStreamProcessorManager().getNominalRate());
96
97     return true;
98 }
99
100
101 /**
102  * Processes packet header to extract timestamps and check if the packet is valid
103  * @param data
104  * @param length
105  * @param channel
106  * @param tag
107  * @param sy
108  * @param cycle
109  * @param dropped
110  * @return
111  */
112 enum StreamProcessor::eChildReturnValue
113 MotuReceiveStreamProcessor::processPacketHeader(unsigned char *data, unsigned int length,
114                   unsigned char channel, unsigned char tag, unsigned char sy,
115                   unsigned int cycle, unsigned int dropped)
116 {
117     if (length > 8) {
118         // The iso data blocks from the MOTUs comprise a CIP-like
119         // header followed by a number of events (8 for 1x rates, 16
120         // for 2x rates, 32 for 4x rates).
121         quadlet_t *quadlet = (quadlet_t *)data;
122         unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size
123         unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits
124
125         // Don't even attempt to process a packet if it isn't what
126         // we expect from a MOTU.  Yes, an FDF value of 32 bears
127         // little relationship to the actual data (24 bit integer)
128         // sent by the MOTU - it's one of those areas where MOTU
129         // have taken a curious detour around the standards.
130         if (tag!=1 || fdf_size!=32) {
131             return eCRV_Invalid;
132         }
133
134         // put this after the check because event_length can become 0 on invalid packets
135         unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes
136         unsigned int n_events = (length-8) / event_length;
137
138         // Acquire the timestamp of the last frame in the packet just
139         // received.  Since every frame from the MOTU has its own timestamp
140         // we can just pick it straight from the packet.
141         uint32_t last_sph = ntohl(*(quadlet_t *)(data+8+(n_events-1)*event_length));
142         m_last_timestamp = sphRecvToFullTicks(last_sph, m_Parent.get1394Service().getCycleTimer());
143         return eCRV_OK;
144     } else {
145         return eCRV_Invalid;
146     }
147 }
148
149 /**
150  * extract the data from the packet
151  * @pre the IEC61883 packet is valid according to isValidPacket
152  * @param data
153  * @param length
154  * @param channel
155  * @param tag
156  * @param sy
157  * @param cycle
158  * @param dropped
159  * @return
160  */
161 enum StreamProcessor::eChildReturnValue
162 MotuReceiveStreamProcessor::processPacketData(unsigned char *data, unsigned int length,
163                   unsigned char channel, unsigned char tag, unsigned char sy,
164                   unsigned int cycle, unsigned int dropped_cycles) {
165     quadlet_t* quadlet = (quadlet_t*) data;
166
167     unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size
168     unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits
169     // this is only called for packets that return eCRV_OK on processPacketHeader
170     // so event_length won't become 0
171     unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes
172     unsigned int n_events = (length-8) / event_length;
173
174     // we have to keep in mind that there are also
175     // some packets buffered by the ISO layer,
176     // at most x=m_handler->getWakeupInterval()
177     // these contain at most x*syt_interval
178     // frames, meaning that we might receive
179     // this packet x*syt_interval*ticks_per_frame
180     // later than expected (the real receive time)
181     #ifdef DEBUG
182     if(isRunning()) {
183         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"STMP: %lluticks | tpf=%f\n",
184             m_last_timestamp, getTicksPerFrame());
185     }
186     #endif
187
188     if(m_data_buffer->writeFrames(n_events, (char *)(data+8), m_last_timestamp)) {
189         return eCRV_OK;
190     } else {
191         return eCRV_XRun;
192     }
193 }
194
195 /***********************************************
196  * Encoding/Decoding API                       *
197  ***********************************************/
198 /**
199  * \brief write received events to the port ringbuffers.
200  */
201 bool MotuReceiveStreamProcessor::processReadBlock(char *data,
202                        unsigned int nevents, unsigned int offset)
203 {
204     bool no_problem=true;
205     for ( PortVectorIterator it = m_Ports.begin();
206           it != m_Ports.end();
207           ++it ) {
208         if((*it)->isDisabled()) {continue;};
209
210         Port *port=(*it);
211
212         switch(port->getPortType()) {
213
214         case Port::E_Audio:
215             if(decodeMotuEventsToPort(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
216                 debugWarning("Could not decode packet data to port %s",(*it)->getName().c_str());
217                 no_problem=false;
218             }
219             break;
220         case Port::E_Midi:
221 //             if(decodeMotuMidiEventsToPort(static_cast<MotuMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) {
222 //                 debugWarning("Could not decode packet midi data to port %s",(*it)->getName().c_str());
223 //                 no_problem=false;
224 //             }
225             break;
226
227         default: // ignore
228             break;
229         }
230     }
231     return no_problem;
232 }
233
234 signed int MotuReceiveStreamProcessor::decodeMotuEventsToPort(MotuAudioPort *p,
235         quadlet_t *data, unsigned int offset, unsigned int nevents)
236 {
237     unsigned int j=0;
238
239     // Use char here since a port's source address won't necessarily be
240     // aligned; use of an unaligned quadlet_t may cause issues on
241     // certain architectures.  Besides, the source (data coming directly
242     // from the MOTU) isn't structured in quadlets anyway; it mainly
243     // consists of packed 24-bit integers.
244
245     unsigned char *src_data;
246     src_data = (unsigned char *)data + p->getPosition();
247
248     switch(m_StreamProcessorManager.getAudioDataType()) {
249         default:
250         case StreamProcessorManager::eADT_Int24:
251             {
252                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
253
254                 assert(nevents + offset <= p->getBufferSize());
255
256                 // Offset is in frames, but each port is only a single
257                 // channel, so the number of frames is the same as the
258                 // number of quadlets to offset (assuming the port buffer
259                 // uses one quadlet per sample, which is the case currently).
260                 buffer+=offset;
261
262                 for(j = 0; j < nevents; j += 1) { // Decode nsamples
263                     *buffer = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
264                     // Sign-extend highest bit of 24-bit int.
265                     // FIXME: this isn't strictly needed since E_Int24 is a 24-bit,
266                     // but doing so shouldn't break anything and makes the data
267                     // easier to deal with during debugging.
268                     if (*src_data & 0x80)
269                         *buffer |= 0xff000000;
270
271                     buffer++;
272                     src_data+=m_event_size;
273                 }
274             }
275             break;
276         case StreamProcessorManager::eADT_Float:
277             {
278                 const float multiplier = 1.0f / (float)(0x7FFFFF);
279                 float *buffer=(float *)(p->getBufferAddress());
280
281                 assert(nevents + offset <= p->getBufferSize());
282
283                 buffer+=offset;
284
285                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
286
287                     unsigned int v = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
288
289                     // sign-extend highest bit of 24-bit int
290                     int tmp = (int)(v << 8) / 256;
291
292                     *buffer = tmp * multiplier;
293
294                     buffer++;
295                     src_data+=m_event_size;
296                 }
297             }
298             break;
299     }
300
301     return 0;
302 }
303
304 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.