Changeset 263
- Timestamp:
- 06/15/06 09:07:47 (17 years ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.cpp
r261 r263 53 53 /* transmit */ 54 54 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(int port, int framerate, int dimension) 55 : TransmitStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0) { 55 : TransmitStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0) 56 , m_dbc(0) { 56 57 57 58 … … 86 87 } 87 88 88 89 89 enum raw1394_iso_disposition 90 90 AmdtpTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length, … … 93 93 94 94 struct iec61883_packet *packet = (struct iec61883_packet *) data; 95 96 95 unsigned int nevents=0; 96 97 packet->eoh0 = 0; 98 99 /* Our node ID can change after a bus reset, so it is best to fetch 100 * our node ID for each packet. */ 101 packet->sid = getNodeId() & 0x3f; 102 103 packet->dbs = m_dimension; 104 packet->fn = 0; 105 packet->qpc = 0; 106 packet->sph = 0; 107 packet->reserved = 0; 108 packet->dbc = m_dbc; 109 packet->eoh1 = 2; 110 packet->fmt = IEC61883_FMT_AMDTP; 111 97 112 // signal that we are running (a transmit stream is always 'runnable') 98 113 m_running=true; … … 102 117 // that means that we'll send NODATA packets FIXME: check!! 103 118 if(m_disabled) { 104 iec61883_cip_fill_header_nodata(getNodeId(), &m_cip_status, packet); 105 *length = 0; // this is to disable sending 119 // no-data packets have syt=0xFFFF 120 // and have the usual amount of events as dummy data 121 packet->fdf = IEC61883_FDF_NODATA; 122 packet->syt = 0xffff; 123 124 // the dbc is incremented even with no data packets 125 m_dbc += m_syt_interval; 126 127 *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t); 106 128 *tag = IEC61883_TAG_WITH_CIP; 107 129 *sy = 0; 108 m_last_timestamp=4.0*9000.0 + cycle * 3072.0;109 130 return RAW1394_ISO_OK; 110 131 } 111 112 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); 113 114 // keep the old cip, in case we don't have enough events left in the buffer. 115 struct iec61883_cip old_cip; 116 memcpy(&old_cip,&m_cip_status,sizeof(struct iec61883_cip)); 117 132 133 packet->fdf = m_fdf; 134 135 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); 136 118 137 // construct the packet cip 138 // NOTE: maybe a little outdated 119 139 // FIXME: this should be done differently: 120 140 // first we should determine the timestamp of the first sample in this block … … 138 158 // <<compile error here>> 139 159 140 int nevents = iec61883_cip_fill_header (getNodeId(), &m_cip_status, packet); 141 142 143 unsigned int timestamp_ticks=m_last_timestamp; // fixed transfer delay 144 timestamp_ticks += 9000; 145 146 // if there are dropped packets, incorporate them into the delay 147 // FIXME: we don't know how many samples were lost 160 // FIXME: if m_last_bufferfill > 0 161 double ticks_per_frame=syncmaster->getTicksPerFrame(); 162 163 // m_last_timestamp is the moment upon which the last 'period signal' 164 // should have been given (note: should have been because 165 // the timestamp is derrived from the incoming packets, 166 // not from the moment the signal was actually given) 167 168 // at a period boundary, we expect nb_buffers * period frames to 169 // be in the buffers. 'right after' the transfer(), all of these 170 // frames should be in the xmit buffers (if transfer() finishes 171 // before new packets are received) 172 // therefore the last sample of the xmit buffer lies at 173 // T1 = timestamp + (nb_buffers * period) * ticks_per_frame 174 int T1 = m_last_timestamp + (m_nb_buffers * m_period) * ticks_per_frame; 175 176 // in reality however life is multithreaded, and we don't know 177 // exactly how many samples there are in the buffer. but we know 178 // how many there should be, so we say that the last frame put 179 // into the buffer (by transfer) has the timestamp T1 180 181 // this means that the current sample has timestamp 182 // T2 = T1 - (nb_frames_in_buffer) * ticks_per_frame 183 int buffer_fill=freebob_ringbuffer_read_space(m_event_buffer)/m_dimension/sizeof(quadlet_t); 184 185 int T2 = T1 - buffer_fill * ticks_per_frame; 186 187 // normally: nb_buffers * period > nb_frames_in_buffer 188 // making T2 > timestamp 189 // however, this isn't always the case, due to ISO buffering etc. 190 // we therefore need to add some extra delay to T2: 191 // T3 = T2 + Tiso 192 // This Tiso has to cope with the prebuffering that has been done 193 // by the ISO layer: e.g. if 100 packets are prebuffered, this 194 // callback is executed approximately 100 packets before the 195 // actual transmission, hence we have to add 100 * 3072 ticks to 196 // the timestamp 197 // we know that one packet occurrs every 1/8000 secs, 198 // therefore the average nb of samples in a packet is m_framerate/8000 199 // making that these 100 packets contain 600 frames, and that 200 // we therefore need to advance the timestamp with the equivalent of 201 // 600 frames (600*ticks_per_frame) 202 int T3 = T2 + (m_handler->getBuffersize() * m_framerate * ticks_per_frame) / 8000; 203 204 // we then need to add the processing delay for the receiving 205 // device to this time to determine the xmit timestamp 206 // TSTAMP = T3 + PROCESSING_DELAY 207 208 // we should determine when to 'queue' this sample to 209 // the ISO xmit layer, based upon the cycle parameter 210 // we can define the ideal time at which to send the sample as 211 // TSEND = TSTAMP - PROCESSING_DELAY 212 // being T3 213 // however, this might make things a little too tight, as it can 214 // be that we are pre-queueing things. We have to make sure that 215 // T3 > timestamp (causality on our side) 216 // and that TSTAMP > timestamp (causality on the receiver's side) 217 218 // so we define TSEND as: 219 // TSEND = T3 + Tslack 220 // Tslack tbd 221 222 // note: Tslack=0 packets 223 int TSEND = T3; 224 225 // if we take a look at TSEND we can determine if we are to send 226 // the sample or not: 227 // if 228 // CYCLES(TSEND) < cycle 229 // then the time at which to send the packet has passed (note: wraparound!) 230 // we should send the sample 231 // if it hasn't passed, we should send an empty packet 232 // 233 // this should automatically catch up 234 235 // FIXME: wraparound! 236 int cycle_wo_wraparound=cycle; 237 238 // arbitrary 239 if (cycle_wo_wraparound - (TSEND/3072) < -4000) { 240 cycle_wo_wraparound +=8000; 241 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"wraparound detected: %d %d %d\n",cycle, cycle_wo_wraparound, cycle - (TSEND/3072)); 242 } 243 244 if (TSEND < cycle_wo_wraparound*3072) { 245 nevents=m_syt_interval; 246 m_dbc += m_syt_interval; 247 } else { // no-data 248 // no-data packets have syt=0xFFFF 249 // and have the usual amount of events as dummy data 250 packet->fdf = IEC61883_FDF_NODATA; 251 packet->syt = 0xffff; 252 253 // the dbc is incremented even with no data packets 254 m_dbc += m_syt_interval; 255 256 *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t); 257 *tag = IEC61883_TAG_WITH_CIP; 258 *sy = 0; 148 259 149 unsigned int timestamp=(((timestamp_ticks/3072) << 12) & 0xF000); 150 timestamp |= ((timestamp_ticks % 3072)) & 0xFFF; 151 152 timestamp = htons(timestamp); 153 154 m_last_timestamp += nevents*syncmaster->getTicksPerFrame(); 155 156 if (nevents==0) { 157 timestamp=0xFFFF; 158 } 260 debugOutput(DEBUG_LEVEL_VERBOSE,"Sending empty packet\n"); 261 262 return RAW1394_ISO_OK; 263 } 264 265 // the xmit timestamp should then be the TSEND + PROCESSING_DELAY 266 int timestamp = TSEND + 3*3072; 267 268 debugOutput(DEBUG_LEVEL_VERBOSE,"Now=%4d/%8d, Tstamp=%8d, DT=%8d, T2=%8d, T3=%8d, last TS=%d, BF=%d\n", 269 cycle,(cycle*3072), 270 timestamp, 271 timestamp-(cycle*3072), 272 T2,T3, 273 m_last_timestamp, 274 buffer_fill); 159 275 160 276 enum raw1394_iso_disposition retval = RAW1394_ISO_OK; 161 277 162 if (!(nevents > 0)) {163 164 if (m_cip_status.mode == IEC61883_MODE_BLOCKING_EMPTY) {165 *length = 8;166 return RAW1394_ISO_OK ;167 }168 else {169 nevents = m_cip_status.syt_interval;170 }171 }172 173 278 int read_size=nevents*sizeof(quadlet_t)*m_dimension; 174 279 … … 182 287 183 288 // signal underrun 184 //m_xruns++;289 m_xruns++; 185 290 186 291 retval=RAW1394_ISO_DEFER; … … 199 304 } 200 305 201 unsigned int timestamp2=ntohs(timestamp); 202 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"XMIT %d EVENTS, SYT %04X (was: %04X) for cycle %2d: %5u ticks (%2u cycles + %04u ticks)\n", 203 nevents, timestamp, packet->syt, cycle, 204 CYCLE_COUNTER_TO_TICKS(timestamp2), 205 CYCLE_COUNTER_GET_CYCLES(timestamp2), 206 CYCLE_COUNTER_GET_TICKS(timestamp2) 207 ); 306 307 // we can forget the seconds for the cycle counter 308 // because we are masking with 0xFFFF 309 unsigned int timestamp_cycles=timestamp/3072; 310 unsigned int timestamp_ticks=timestamp%3072; 311 timestamp_cycles %= 8000; 312 313 unsigned int timestamp_cyclecounter = (timestamp_cycles << 12) | timestamp_ticks; 314 315 packet->syt = ntohs(timestamp_cyclecounter & 0xffff); 316 317 debugOutput(DEBUG_LEVEL_VERBOSE,"XMIT %d EVENTS, SYT %04X for cycle %2d: %08d (%2u cycles + %04u ticks)\n", 318 nevents, timestamp_cyclecounter & 0xFFFF, cycle, 319 CYCLE_COUNTER_TO_TICKS(timestamp_cyclecounter), 320 CYCLE_COUNTER_GET_CYCLES(timestamp_cyclecounter), 321 CYCLE_COUNTER_GET_TICKS(timestamp_cyclecounter) 322 ); 208 323 } 209 324 … … 211 326 *sy = 0; 212 327 213 // FIXME: do this directly214 packet->syt=timestamp;215 216 328 // update the frame counter 217 329 incrementFrameCounter(nevents); 330 218 331 if(m_framecounter>m_period) { 219 332 retval=RAW1394_ISO_DEFER; … … 222 335 #ifdef DEBUG 223 336 if(packet->dbs) { 224 debugOutput(DEBUG_LEVEL_VER BOSE,337 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, 225 338 "XMT: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n", 226 339 m_channel, packet->fdf, … … 232 345 ((*length / sizeof (quadlet_t)) - 2)/packet->dbs); 233 346 } 234 #endif 235 347 #endif 348 236 349 m_PacketStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 237 350 238 351 return retval; 239 352 353 } 354 355 void AmdtpTransmitStreamProcessor::decrementFrameCounter() { 356 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "decrement frame counter...\n"); 357 358 #ifdef DEBUG 359 int xmit_bufferspace=freebob_ringbuffer_read_space(m_event_buffer)/m_dimension/4; 360 int recv_bufferspace=freebob_ringbuffer_read_space(syncmaster->m_event_buffer)/syncmaster->m_dimension/4; 361 362 debugOutput(DEBUG_LEVEL_VERBOSE,"XMT: %5d | RCV: %5d | DIFF: %5d | SUM: %5d \n", xmit_bufferspace, recv_bufferspace, xmit_bufferspace - recv_bufferspace, xmit_bufferspace + recv_bufferspace); 363 #endif 364 365 // update the timestamp 366 367 m_last_timestamp=syncmaster->getPeriodTimeStamp(); 368 369 StreamProcessor::decrementFrameCounter(); 370 } 371 372 void AmdtpTransmitStreamProcessor::incrementFrameCounter(int nbframes) { 373 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "increment frame counter by %d...\n", nbframes); 374 375 StreamProcessor::incrementFrameCounter(nbframes); 240 376 } 241 377 242 378 bool AmdtpTransmitStreamProcessor::isOnePeriodReady() 243 379 { 244 //return true;245 380 return true; 381 //return (m_framecounter > (int)m_period); 246 382 } 247 383 … … 965 1101 #endif 966 1102 967 const double coeff=0.000 1;1103 const double coeff=0.0005; 968 1104 // integrate the error 969 1105 m_ticks_per_frame += coeff*err; … … 971 1107 } 972 1108 973 debugOutput(DEBUG_LEVEL_VER Y_VERBOSE,"R-SYT for cycle (%2d %2d)=>%2d: %5uT (%04uC + %04uT) %04X %04X %d\n",1109 debugOutput(DEBUG_LEVEL_VERBOSE,"R-SYT for cycle (%2d %2d)=>%2d: %5uT (%04uC + %04uT) %04X %04X %d\n", 974 1110 cycle,now_cycle_masked,delta_cycles, 975 1111 CYCLE_COUNTER_TO_TICKS(m_last_timestamp), … … 997 1133 #ifdef DEBUG 998 1134 if(packet->dbs) { 999 debugOutput(DEBUG_LEVEL_VER BOSE,1135 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, 1000 1136 "RCV: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n", 1001 1137 channel, packet->fdf, … … 1119 1255 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Periods: %d, remote ticks/frame: %f, remote framerate = %f\n",m_PeriodStat.m_count, m_ticks_per_frame, 24576000.0/m_ticks_per_frame); 1120 1256 if (-tmp>1000000) debugWarning("SYT VERY LATE: %d!\n",-tmp); 1121 // return true; 1257 1258 m_last_timestamp_at_period_ticks=ideal_presentation_time; 1259 return true; 1122 1260 } else { 1123 1261 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Too early wait %d ticks\n",tmp); 1124 //return false;1262 return false; 1125 1263 } 1126 } 1127 // else return false; 1128 // #else 1264 } else { 1265 return false; 1266 } 1267 #else 1129 1268 if(m_framecounter > (int)m_period) { 1130 1269 return true; branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.h
r255 r263 73 73 74 74 public: 75 75 // FIXME: debug 76 friend class AmdtpReceiveStreamProcessor; 77 76 78 AmdtpTransmitStreamProcessor(int port, int framerate, int dimension); 77 79 … … 105 107 AmdtpReceiveStreamProcessor *syncmaster; 106 108 109 // this updates the timestamp, and the 110 // 'bufferfill' 111 // should be called from the same thread 112 // that does the iteration 113 void decrementFrameCounter(); 114 void incrementFrameCounter(int nbframes); 115 107 116 protected: 108 117 … … 132 141 unsigned int offset, unsigned int nevents); 133 142 134 double m_last_timestamp; 135 143 unsigned int m_last_timestamp; 144 145 unsigned int m_dbc; 136 146 137 147 DECLARE_DEBUG_MODULE; … … 150 160 151 161 public: 162 // FIXME: debug 163 friend class AmdtpTransmitStreamProcessor; 152 164 153 165 AmdtpReceiveStreamProcessor(int port, int framerate, int dimension); … … 181 193 182 194 double getTicksPerFrame() {return m_ticks_per_frame;}; 183 195 unsigned int getPeriodTimeStamp() {return m_last_timestamp_at_period_ticks;}; 196 184 197 void dumpInfo(); 185 198 … … 198 211 unsigned int m_last_timestamp; 199 212 unsigned int m_last_timestamp2; 213 unsigned int m_last_timestamp_at_period_ticks; 200 214 201 215 double m_ticks_per_frame; branches/libfreebob-2.0/src/libstreaming/StreamProcessor.h
r249 r263 87 87 88 88 unsigned int getNbPeriodsReady() { if(m_period) return m_framecounter/m_period; else return 0;}; 89 v oid decrementFrameCounter();90 v oid incrementFrameCounter(int nbframes);89 virtual void decrementFrameCounter(); 90 virtual void incrementFrameCounter(int nbframes); 91 91 92 92 // move to private?