void runAsClient() { timeStampServerLast = Thread::getTimeStampMs(); ThroughputReceiver tpRcvr; DiscoveryTimeGreeter discGreeter; reporter = Publisher("reports"); reporter.setGreeter(&discGreeter); Subscriber tcpSub("throughput.tcp"); tcpSub.setReceiver(&tpRcvr); SubscriberConfigMCast mcastConfig("throughput.mcast"); mcastConfig.setMulticastIP("224.1.2.3"); mcastConfig.setMulticastPortbase(22022); Subscriber mcastSub(&mcastConfig); mcastSub.setReceiver(&tpRcvr); SubscriberConfigRTP rtpConfig("throughput.rtp"); // rtpConfig.setPortbase(40042); Subscriber rtpSub(&rtpConfig); rtpSub.setReceiver(&tpRcvr); node.addSubscriber(tcpSub); node.addSubscriber(mcastSub); node.addSubscriber(rtpSub); node.addPublisher(reporter); disc.add(node); timeStampStartedPublishing = Thread::getTimeStampMs(); // do nothing here, we reply only when we received a message while(true) { #if 0 Thread::sleepMs(1000); #else // disconnect / reconnect client on key-press getchar(); node.removeSubscriber(tcpSub); node.removeSubscriber(mcastSub); node.removeSubscriber(rtpSub); node.removePublisher(reporter); disc.remove(node); getchar(); disc.add(node); node.addSubscriber(tcpSub); node.addSubscriber(mcastSub); node.addSubscriber(rtpSub); node.addPublisher(reporter); #endif } }
void runAsServer() { ThroughputGreeter tpGreeter; Publisher pub; switch (type) { case PUB_RTP: { PublisherConfigRTP config("throughput.rtp"); config.setTimestampIncrement(166); pub = Publisher(&config); pub.setGreeter(&tpGreeter); break; } case PUB_MCAST: { PublisherConfigMCast config("throughput.mcast"); config.setTimestampIncrement(166); // config.setPortbase(42142); pub = Publisher(&config); pub.setGreeter(&tpGreeter); break; } case PUB_TCP: { pub = Publisher("throughput.tcp"); pub.setGreeter(&tpGreeter); break; } } node.addPublisher(pub); disc.add(node); timeStampStartedAt = Thread::getTimeStampMs(); if (duration > 0) duration *= 1000; // convert to ms pub.waitForSubscribers(waitForSubs); // reserve 20 bytes for timestamp, sequence number and report interval size_t dataSize = (std::max)(mtu, (size_t)20); char* data = (char*)malloc(dataSize); Message* msg = NULL; if (useZeroCopy) { msg = new Message(data, dataSize, doneCallback, (void*)NULL); } else { msg = new Message(); } uint64_t lastReportAt = Thread::getTimeStampMs(); while(1) { uint64_t now = Thread::getTimeStampMs(); if (duration > 0 && now - timeStampStartedAt > duration) break; // first 16 bytes are seqNr and timestamp Message::write(&data[0], ++currSeqNr); Message::write(&data[8], now); Message::write(&data[16], reportInterval); if (!useZeroCopy) { msg->setData(data, dataSize); } pub.send(msg); intervalFactor = 1000.0 / (double)reportInterval; bytesWritten += dataSize; bytesTotal += dataSize; packetsWritten++; // sleep just enough to reach the desired bps { RScopeLock lock(mutex); size_t packetsPerSecond = (std::max)(bytesPerSecond / dataSize, (size_t)1); delay = (std::max)((1000000) / (packetsPerSecond), (size_t)1); } // every report interval we are recalculating bandwith if (now - lastReportAt > reportInterval) { RScopeLock lock(mutex); std::string scaleInfo("--"); // and recalculate bytes to send if (reports.size() > 0) { double decreasePressure = 0; // print report messages std::map<std::string, Report>::iterator repIter = reports.begin(); // bandwidth is not fixed if (fixedBytesPerSecond == 0) { while(repIter != reports.end()) { const Report& report = repIter->second; double reportPressure = 0; // see if we need to decrease bandwidth if (report.pktsLate > packetsWritten / 2) { // client is lagging more than half a second, scale back somewhat reportPressure = (std::max)(1.1, reportPressure); } if (report.pcntLoss > pcntLossOk) { // we lost packages, scale back somewhat reportPressure = (std::max)((double)report.pktsDropped / report.pktsRcvd, reportPressure); reportPressure = (std::min)(reportPressure, 1.4); } if (report.pktsLate > 3 * packetsWritten) { // queues explode! scale back alot! reportPressure = (std::max)((double)report.pktsLate / packetsWritten, reportPressure); reportPressure = (std::min)(reportPressure, 2.0); } if (reportPressure > decreasePressure) decreasePressure = reportPressure; repIter++; } if (decreasePressure > 1) { bytesPerSecond *= (1.0 / decreasePressure); bytesPerSecond = (std::max)(bytesPerSecond, (size_t)(1024)); scaleInfo = "down " + toStr(1.0 / decreasePressure); } else { bytesPerSecond *= 1.2; scaleInfo = "up 1.2"; } std::cout << std::endl; } else { if (bytesWritten * intervalFactor < fixedBytesPerSecond) { bytesPerSecond *= 1.05; } else if (bytesWritten * intervalFactor > fixedBytesPerSecond) { bytesPerSecond *= 0.95; } } } currReportNr++; writeReports(scaleInfo); bytesWritten = 0; packetsWritten = 0; lastReportAt = Thread::getTimeStampMs(); } // now we sleep until we have to send another packet Thread::sleepUs(delay); } pub.setGreeter(NULL); delete(msg); }
void runAsServer() { ThroughputGreeter tpGreeter; Publisher pub; PublisherConfig* config = NULL; switch (type) { case PUB_RTP: { config = new PublisherConfigRTP("throughput.rtp"); ((PublisherConfigRTP*)config)->setTimestampIncrement(166); break; } case PUB_MCAST: { config = new PublisherConfigMCast("throughput.mcast"); ((PublisherConfigMCast*)config)->setTimestampIncrement(166); // config.setPortbase(42142); break; } case PUB_TCP: { config = new PublisherConfigTCP ("throughput.tcp"); break; } } if (compressionType.size() != 0) config->enableCompression(compressionType, compressionWithState, compressionLevel, compressionRefreshInterval); pub = Publisher(config); pub.setGreeter(&tpGreeter); delete config; node.addPublisher(pub); disc.add(node); timeStampStartedDiscovery = Thread::getTimeStampMs(); if (duration > 0) duration *= 1000; // convert to ms // open file with data std::ifstream fin(streamFile, std::ios::in | std::ios::binary); if (fin) { // streamFile exists on filesyste,, slurp content into streamData streamData = std::string((std::istreambuf_iterator<char>(fin) ), (std::istreambuf_iterator<char>() )); } else { // stream file is no actual file, interpret as "size:compressability" char* compArg = streamFile; // http://stackoverflow.com/a/53878/990120 std::list<std::string> compArgs; do { const char *begin = compArg; while(*compArg != ':' && *compArg) compArg++; compArgs.push_back(std::string(begin, compArg - begin)); } while(0 != *compArg++); size_t streamDataSize = 0; double compressibility = 50; if (compArgs.size() < 1) printUsageAndExit(); streamDataSize = displayToBytes(compArgs.front()); compArgs.pop_front(); if (!compArgs.empty()) { compressibility = strTo<double>(compArgs.front()); if (toStr(compressibility) != compArgs.front()) printUsageAndExit(); compArgs.pop_front(); } if (!compArgs.empty()) { printUsageAndExit(); } streamData.resize(streamDataSize); RDG_genBuffer(&streamData[0], streamDataSize, 1 - (compressibility/(double)100), 0.0, 0); } { // determine compressionActualRatio Message msg(streamData.data(), streamData.size()); size_t compressMaxPayload = msg.getCompressBounds("lz4", NULL, Message::Compression::PAYLOAD); char* compressPayloadData = (char*)malloc(compressMaxPayload); size_t compressActualPayload = msg.compress("lz4", NULL, compressPayloadData, compressMaxPayload, Message::Compression::PAYLOAD); compressionActualRatio = 100 * ((double)compressActualPayload / streamData.size()); } pub.waitForSubscribers(waitForSubs); timeStampStartedPublishing = Thread::getTimeStampMs(); uint64_t lastReportAt = Thread::getTimeStampMs(); size_t streamDataOffset = 0; while(1) { // fill data from stream data Message* msg = new Message((char*)malloc(mtu), mtu); size_t msgDataOffset = 0; while(true) { size_t toRead = (mtu - msgDataOffset <= streamData.size() - streamDataOffset ? mtu - msgDataOffset : streamData.size() - streamDataOffset); memcpy(&msg->data()[msgDataOffset], &streamData[streamDataOffset], toRead); msgDataOffset += toRead; streamDataOffset += toRead; // UM_LOG_WARN("%d: %d / %d", streamData.size(), msgDataOffset, streamDataOffset); if (msgDataOffset == mtu) break; if (streamData.size() == streamDataOffset) streamDataOffset = 0; } // UM_LOG_WARN("%d: %s", msg->size(), md5(msg->data(), msg->size()).c_str()); uint64_t now = Thread::getTimeStampMs(); if (duration > 0 && now - timeStampStartedPublishing > duration) break; // first 16 bytes are seqNr and timestamp Message::write(&msg->data()[0], ++currSeqNr); Message::write(&msg->data()[8], now); Message::write(&msg->data()[16], reportInterval); // msg->putMeta("md5", md5(msg->data(), msg->size())); intervalFactor = 1000.0 / (double)reportInterval; bytesWritten += msg->size(); bytesTotal += msg->size(); packetsWritten++; // sleep just enough to reach the desired bps { RScopeLock lock(mutex); size_t packetsPerSecond = (std::max)(bytesPerSecond / msg->size(), (size_t)1); delay = (std::max)((1000000) / (packetsPerSecond), (size_t)1); } // sending with compression will alter msg->size(); not anymore ... pub.send(msg); // every report interval we are recalculating bandwith if (now - lastReportAt > reportInterval) { RScopeLock lock(mutex); std::string scaleInfo("--"); // and recalculate bytes to send if (reports.size() > 0) { double decreasePressure = 0; // print report messages std::map<std::string, Report>::iterator repIter = reports.begin(); // bandwidth is fixed if (fixedBytesPerSecond == 0) { while(repIter != reports.end()) { const Report& report = repIter->second; double reportPressure = 0; // see if we need to decrease bandwidth if (report.pktsLate > packetsWritten / 2) { // client is lagging more than half a second, scale back somewhat reportPressure = (std::max)(1.1, reportPressure); } if (report.pcntLoss > pcntLossOk) { // we lost packages, scale back somewhat reportPressure = (std::max)((double)report.pktsDropped / report.pktsRcvd, reportPressure); reportPressure = (std::min)(reportPressure, 1.4); } if (report.pktsLate > 3 * packetsWritten) { // queues explode! scale back alot! reportPressure = (std::max)((double)report.pktsLate / packetsWritten, reportPressure); reportPressure = (std::min)(reportPressure, 2.0); } if (reportPressure > decreasePressure) decreasePressure = reportPressure; repIter++; } if (decreasePressure > 1) { bytesPerSecond *= (1.0 / decreasePressure); bytesPerSecond = (std::max)(bytesPerSecond, (size_t)(1024)); scaleInfo = "down " + toStr(1.0 / decreasePressure); } else { bytesPerSecond *= 1.3; scaleInfo = "up 1.3"; } std::cout << std::endl; } else if (fixedBytesPerSecond == (size_t)-1) { // do nothing } else { if (bytesWritten * intervalFactor < fixedBytesPerSecond) { bytesPerSecond *= 1.05; } else if (bytesWritten * intervalFactor > fixedBytesPerSecond) { bytesPerSecond *= 0.95; } } } currReportNr++; writeReports(scaleInfo); bytesWritten = 0; packetsWritten = 0; lastReportAt = Thread::getTimeStampMs(); } delete(msg); // now we sleep until we have to send another packet if (delay > 50 && fixedBytesPerSecond != (size_t) - 1) Thread::sleepUs(delay); } pub.setGreeter(NULL); }
int main(int argc, char** argv) { uint16_t modulo = 1; Freenect::Freenect freenect; FreenectBridge* device; Discovery disc; Node node; Publisher pubDepthTCP; Publisher pubDepthRTP; Publisher pubVideoTCP; Publisher pubVideoRTP; printf("umundo-kinect-pub version " UMUNDO_VERSION " (" CMAKE_BUILD_TYPE " build)\n"); int option; while ((option = getopt(argc, argv, "m:")) != -1) { switch(option) { case 'm': modulo = atoi(optarg); break; default: printUsageAndExit(); break; } } std::cout << "Sending every " << modulo << ". frame..." << std::endl << std::flush; { PublisherConfigRTP pubConfigRTP("kinect.depth.rtp"); pubConfigRTP.setTimestampIncrement(1); pubDepthRTP = Publisher(&pubConfigRTP); PublisherConfigTCP pubConfigTCP("kinect.depth.tcp"); pubConfigTCP.enableCompression(); pubDepthTCP = Publisher(&pubConfigTCP); } { PublisherConfigRTP pubConfigRTP("kinect.video.rtp"); pubConfigRTP.setTimestampIncrement(1); pubVideoRTP = Publisher(&pubConfigRTP); PublisherConfigTCP pubConfigTCP("kinect.video.tcp"); pubConfigTCP.enableCompression(); pubVideoTCP = Publisher(&pubConfigTCP); } disc = Discovery(Discovery::MDNS); disc.add(node); node.addPublisher(pubDepthRTP); node.addPublisher(pubDepthTCP); node.addPublisher(pubVideoRTP); node.addPublisher(pubVideoTCP); // try to instantiate freenect device while(true) { try { // constructor is somewhat fragile device = &freenect.createDevice<FreenectBridge>(0); device->pubDepthRTP = pubDepthRTP; device->pubDepthTCP = pubDepthTCP; device->pubVideoRTP = pubVideoRTP; device->pubVideoTCP = pubVideoTCP; device->setModulo(modulo); // this is actually the default device->setVideoFormat(FREENECT_VIDEO_BAYER, FREENECT_RESOLUTION_MEDIUM); while(true) { try { device->startVideo(); // not blocking on recent versions only? while(true) Thread::sleepMs(2000); } catch(std::runtime_error e) { std::cout << "An exception occured while trying to start video: " << e.what() << " - retrying after 5s" << std::endl; Thread::sleepMs(5000); } } } catch(std::runtime_error e) { std::cout << "An exception occured: " << e.what() << " - retrying" << std::endl; Thread::sleepMs(5000); } } return 0; }