├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── dependencies ├── binaries │ ├── osx │ │ └── libglfw3.a │ └── win64 │ │ └── glfw3.lib └── headers │ ├── glfw3.h │ └── glfw3native.h ├── examples ├── auto-level-button.png ├── example-desktop-server.cpp └── record-button.png ├── headers ├── blobs.h ├── blobs.hpp ├── camera-calibration.h ├── camera-calibration.hpp ├── camera-fixedparams.h ├── camera-fixedparams.hpp ├── camera-frame.h ├── camera-frame.hpp ├── camera-pose.h ├── camera-pose.hpp ├── clients.h ├── clients.hpp ├── context.h ├── context.hpp ├── core │ ├── bitstream.h │ ├── bitstream.hpp │ ├── bytes.h │ ├── bytes.hpp │ ├── chunks.h │ ├── chunks.hpp │ ├── clocks.h │ ├── clocks.hpp │ ├── config.h │ ├── datagrams.h │ ├── datagrams.hpp │ ├── enum.h │ ├── enum.hpp │ ├── logging.h │ ├── macros.h │ ├── memory.h │ ├── memory.hpp │ ├── platform.h │ ├── platform.hpp │ ├── platforms │ │ ├── core │ │ │ ├── apple-image-codecs.h │ │ │ ├── apple-image-codecs.hpp │ │ │ ├── apple.h │ │ │ ├── apple.hpp │ │ │ ├── bsd-sockets.h │ │ │ ├── bsd-sockets.hpp │ │ │ ├── objc.h │ │ │ ├── objc.hpp │ │ │ ├── posix.h │ │ │ ├── posix.hpp │ │ │ ├── pthreads.h │ │ │ ├── pthreads.hpp │ │ │ ├── win32-api.h │ │ │ ├── windows-image-codecs.h │ │ │ ├── windows-image-codecs.hpp │ │ │ ├── windows-sockets.h │ │ │ ├── windows-sockets.hpp │ │ │ ├── windows-threads.h │ │ │ └── windows-threads.hpp │ │ ├── ios.h │ │ ├── ios.hpp │ │ ├── osx.h │ │ ├── osx.hpp │ │ ├── windows.h │ │ └── windows.hpp │ ├── profiling.h │ ├── queues.h │ ├── queues.hpp │ ├── serializers.h │ ├── serializers.hpp │ ├── shift2depth.h │ ├── shift2depth.hpp │ ├── streams.h │ ├── streams.hpp │ ├── threads.h │ ├── threads.hpp │ ├── types.h │ ├── types.hpp │ ├── wires.h │ └── wires.hpp ├── desktop-server.h ├── desktop-server.hpp ├── desktop-ui.h ├── desktop-ui.hpp ├── discovery.h ├── discovery.hpp ├── endpoints.h ├── endpoints.hpp ├── image-codecs.h ├── image-codecs.hpp ├── image.h ├── image.hpp ├── message.h ├── message.hpp ├── messages.h ├── messages.hpp ├── motion.h ├── motion.hpp ├── servers.h ├── servers.hpp ├── services.h ├── services.hpp ├── sessions-settings.h ├── sessions-settings.hpp ├── sessions-setup-presets.h ├── sessions-setup-presets.hpp ├── sessions-setup.h ├── sessions-setup.hpp ├── shift-depth-converter.h ├── shift-depth-converter.hpp └── uplink.h ├── projects ├── uplink-vs2012-example-server.vcxproj ├── uplink-vs2012.sln ├── uplink-vs2013-example-server.vcxproj └── uplink-vs2013.sln ├── scripts ├── build-cmake-make.sh ├── build-cmake-nmake.cmd ├── build-cmake-vs2012.cmd ├── build-cmake-vs2013.cmd └── build-cmake-xcode.sh └── sources ├── uplink.cpp └── uplink.mm /.gitignore: -------------------------------------------------------------------------------- 1 | *.vcxproj.user 2 | *.sdf 3 | *.opensdf 4 | *.suo 5 | builds 6 | CMakeLists.txt.user 7 | trash/ 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | 3 | project(uplink) 4 | 5 | include_directories( 6 | headers 7 | sources 8 | dependencies/headers 9 | ) 10 | 11 | file(GLOB_RECURSE uplink_SOURCES headers/*) 12 | 13 | list(APPEND uplink_SOURCES 14 | sources/uplink.cpp 15 | ) 16 | 17 | set(uplink_LIBS) 18 | 19 | if(WIN32) 20 | list(APPEND uplink_LIBS 21 | Gdiplus 22 | Shlwapi 23 | glfw3 24 | OpenGL32 25 | ) 26 | 27 | if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) 28 | link_directories( 29 | dependencies/binaries/win64 30 | ) 31 | endif() 32 | elseif(APPLE) 33 | list(APPEND uplink_LIBS 34 | "-framework CoreFoundation" 35 | "-framework Cocoa" 36 | "-framework OpenGL" 37 | "-framework CoreVideo" 38 | "-framework IOKit" 39 | glfw3 40 | ) 41 | if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) 42 | link_directories( 43 | dependencies/binaries/osx 44 | ) 45 | endif() 46 | endif() 47 | 48 | macro(uplink_app name) # source ... 49 | add_executable(${name} ${uplink_SOURCES} "${ARGN}") 50 | target_link_libraries(${name} ${uplink_LIBS}) 51 | target_compile_features(${name} PRIVATE 52 | cxx_lambdas 53 | ) 54 | endmacro() 55 | 56 | uplink_app(example-server examples/example-desktop-server.cpp) 57 | 58 | file(COPY 59 | 60 | examples/auto-level-button.png 61 | examples/example-desktop-server.cpp 62 | 63 | DESTINATION . # relative to build directory 64 | ) 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Occipital, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Uplink 2 | 3 | Welcome to Uplink, Occipital's cross-platform RGBD streaming library. 4 | 5 | It was created to connect together desktop applications and the [Structure Sensor](http://structure.io) running on an iOS mobile device. 6 | 7 | And of course, this is the code behind [Skanect](http://skanect.com)'s Uplink feature. 8 | 9 | It is written in C++ 98 (with some occasional C++ 11), and is mostly header-only. 10 | 11 | ## Supported Transmit-Side Platforms 12 | 13 | ### iOS 14 | 15 | You can stream from an iOS device with Structure Sensor plugged into it. *NOTE 2017.10.11 -- A transmit app is not currently provided, but is planned. We will remove this message and provide instructions with how to access it when it is available.* 16 | 17 | ## Supported Receive-Side Platforms 18 | 19 | ### Windows 20 | 21 | An example server can be found [here](./examples/example-desktop-server.cpp). 22 | 23 | ### Other Platforms 24 | 25 | The source code provided may be made to compile with modest effort on other platforms. Please submit a pull request if you manage to get it working on other platforms. 26 | 27 | ## Getting Started 28 | 29 | Both a CMake [project](./CMakeLists.txt) and platform-specific [projects](./projects) (Visual Studio 2012 & 2013) are maintained. 30 | 31 | Pick your favorite, then simply build and run. 32 | 33 | No non-standard external dependencies are required, other than the tiny ones already included for the desktop server UI. 34 | -------------------------------------------------------------------------------- /dependencies/binaries/osx/libglfw3.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structureio/uplink/6aab0f7b55587426d149873c3b21c519cf587e23/dependencies/binaries/osx/libglfw3.a -------------------------------------------------------------------------------- /dependencies/binaries/win64/glfw3.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structureio/uplink/6aab0f7b55587426d149873c3b21c519cf587e23/dependencies/binaries/win64/glfw3.lib -------------------------------------------------------------------------------- /examples/auto-level-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structureio/uplink/6aab0f7b55587426d149873c3b21c519cf587e23/examples/auto-level-button.png -------------------------------------------------------------------------------- /examples/record-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/structureio/uplink/6aab0f7b55587426d149873c3b21c519cf587e23/examples/record-button.png -------------------------------------------------------------------------------- /headers/blobs.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "message.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | struct Blob : Message 14 | { 15 | UPLINK_MESSAGE_CLASS(Blob) 16 | 17 | Blob () 18 | : tag(0) 19 | { 20 | } 21 | 22 | virtual bool serializeWith (Serializer &serializer) 23 | { 24 | if(serializer.isReader()) 25 | { 26 | return_false_unless(serializer.asReader().read(tag)); 27 | 28 | uint32 size; 29 | return_false_unless(serializer.asReader().read(size)); 30 | 31 | // FIXME: Maximum size check. 32 | 33 | data.resize(size); 34 | serializer.asReader().readBytes(data.data(), size); 35 | } 36 | else 37 | { 38 | return_false_unless(serializer.asWriter().write(tag)); 39 | size_t size = data.size(); 40 | return_false_unless(serializer.asWriter().write(uint32(size))); 41 | return_false_unless(serializer.asWriter().writeBytes(data.data(), size)); 42 | } 43 | 44 | return true; 45 | } 46 | 47 | void swapWith (Blob& other) 48 | { 49 | Message::swapWith(other); 50 | 51 | uplink_swap(tag , other.tag); 52 | uplink_swap(data, other.data); 53 | } 54 | 55 | uint8 tag; 56 | std::vector data; 57 | }; 58 | 59 | 60 | //------------------------------------------------------------------------------ 61 | 62 | // FIXME: Move this somewhere else. 63 | 64 | struct Blobs : Serializable 65 | { 66 | enum { MaxNumBlobs = 0x10000 }; 67 | 68 | Blobs () 69 | { 70 | } 71 | 72 | virtual bool serializeWith (Serializer &s) 73 | { 74 | if(s.isReader()) 75 | { 76 | Reader& r = s.asReader(); 77 | 78 | uint16 numBlobs; 79 | 80 | return_false_unless(r.read(numBlobs)); 81 | 82 | blobs.resize(numBlobs); 83 | } 84 | else 85 | { 86 | Writer& w = s.asWriter(); 87 | 88 | size_t numBlobs_ = blobs.size(); 89 | 90 | assert (0 <= numBlobs_ && numBlobs_ < MaxNumBlobs); 91 | 92 | uint16 numBlobs = uint16(numBlobs_); 93 | 94 | return_false_unless(w.write(numBlobs)); 95 | } 96 | 97 | for (int n = 0; n < blobs.size(); ++n) 98 | return_false_unless(blobs[n].serializeWith(s)); 99 | 100 | return true; 101 | } 102 | 103 | void swapWith (Blobs& other) 104 | { 105 | uplink_swap(blobs, other.blobs); 106 | } 107 | 108 | std::vector blobs; 109 | }; 110 | 111 | //------------------------------------------------------------------------------ 112 | 113 | } // uplink namespace 114 | 115 | # include "blobs.h" 116 | -------------------------------------------------------------------------------- /headers/blobs.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "blobs.h" 8 | -------------------------------------------------------------------------------- /headers/camera-calibration.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/types.h" 8 | # include "./message.h" 9 | # include 10 | 11 | namespace uplink { 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | class CameraCalibration : public Serializable 16 | { 17 | public: 18 | CameraCalibration (); 19 | 20 | public: 21 | bool isValid () const; 22 | 23 | public: 24 | void reset (); 25 | 26 | public: 27 | void swapWith (CameraCalibration&); 28 | 29 | public: 30 | bool serializeWith (Serializer& serializer); 31 | 32 | public: 33 | bool operator== (const CameraCalibration& rhs) const; 34 | 35 | public: 36 | float fx; 37 | float fy; 38 | float cx; 39 | float cy; 40 | float tx, ty, tz; 41 | float qx, qy, qz, qw; 42 | float k1, k2, k3; 43 | float p1, p2; 44 | }; 45 | 46 | //------------------------------------------------------------------------------ 47 | 48 | // FIXME: This should be a more free-form property bag, eventually. 49 | struct CameraProperties : Serializable 50 | { 51 | CameraProperties (); 52 | 53 | virtual void swapWith (CameraProperties& other); 54 | 55 | virtual bool serializeWith (Serializer& serializer); 56 | 57 | double exposureTime; 58 | uint16 whiteBalanceMode; 59 | float focusPosition; 60 | }; 61 | 62 | //------------------------------------------------------------------------------ 63 | 64 | struct CameraInfo : Serializable 65 | { 66 | CameraInfo (); 67 | CameraInfo (double timestamp, double duration, CameraCalibration calibration, CameraProperties properties); 68 | 69 | virtual void swapWith (CameraInfo& other); 70 | 71 | virtual bool serializeWith (Serializer& serializer); 72 | 73 | double timestamp; 74 | double duration; 75 | CameraCalibration calibration; 76 | CameraProperties properties; 77 | 78 | // FIXME: Split depth and color camera info. 79 | 80 | // Fixed params 81 | float cmosAndEmitterDistance; 82 | float referencePlaneDistance; 83 | float planePixelSize; 84 | 85 | // Depth stream params 86 | int32 pixelSizeFactor; 87 | int32 streamConfig; 88 | bool isRegisteredToColor; 89 | 90 | // FIXME: For future extension. 91 | bool unused0; 92 | bool unused1; 93 | float unused2; 94 | float unused3; 95 | }; 96 | 97 | //------------------------------------------------------------------------------ 98 | 99 | } 100 | 101 | # include "camera-calibration.hpp" 102 | -------------------------------------------------------------------------------- /headers/camera-calibration.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./camera-calibration.h" 8 | # include "./core/macros.h" 9 | # include 10 | 11 | namespace uplink { 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | # define MEMBERS() \ 16 | MEMBER(fx) \ 17 | MEMBER(fy) \ 18 | MEMBER(cx) \ 19 | MEMBER(cy) \ 20 | MEMBER(tx) \ 21 | MEMBER(ty) \ 22 | MEMBER(tz) \ 23 | MEMBER(qx) \ 24 | MEMBER(qy) \ 25 | MEMBER(qz) \ 26 | MEMBER(qw) \ 27 | MEMBER(k1) \ 28 | MEMBER(k2) \ 29 | MEMBER(k3) \ 30 | MEMBER(p1) \ 31 | MEMBER(p2) 32 | 33 | inline 34 | CameraCalibration::CameraCalibration () 35 | : Serializable() 36 | # define MEMBER(Name) \ 37 | , Name(-FLT_MAX) 38 | MEMBERS() 39 | # undef MEMBER 40 | {} 41 | 42 | inline bool 43 | CameraCalibration::isValid () const 44 | { 45 | return fx > 0.f; 46 | } 47 | 48 | inline void 49 | CameraCalibration::reset () 50 | { 51 | *this = CameraCalibration(); 52 | } 53 | 54 | inline bool 55 | CameraCalibration::operator== (const CameraCalibration& rhs) const 56 | { 57 | // If two members are NAN, we consider they are the same. 58 | 59 | # define MEMBER(Name) \ 60 | if (Name != rhs.Name && !(isnan(Name) && isnan(rhs.Name))) \ 61 | return false; 62 | MEMBERS() 63 | # undef MEMBER 64 | 65 | return true; 66 | } 67 | 68 | inline void 69 | CameraCalibration::swapWith (CameraCalibration& other) 70 | { 71 | # define MEMBER(Name) \ 72 | uplink_swap(Name, other.Name); 73 | MEMBERS() 74 | # undef MEMBER 75 | } 76 | 77 | inline bool 78 | CameraCalibration::serializeWith (Serializer& s) 79 | { 80 | # define MEMBER(Name) \ 81 | report_false_unless("cannot archive camera calibration member: " #Name, s.put(Name)); 82 | MEMBERS() 83 | # undef MEMBER 84 | 85 | return true; 86 | } 87 | 88 | # undef MEMBERS 89 | 90 | //------------------------------------------------------------------------------ 91 | 92 | inline 93 | CameraProperties::CameraProperties () 94 | : exposureTime(-1.) 95 | , whiteBalanceMode(0xFFFF) 96 | {} 97 | 98 | # define MEMBERS() \ 99 | MEMBER(exposureTime) \ 100 | MEMBER(whiteBalanceMode) \ 101 | MEMBER(focusPosition) 102 | 103 | inline void 104 | CameraProperties::swapWith (CameraProperties& other) 105 | { 106 | # define MEMBER(Name) \ 107 | uplink_swap(Name, other.Name); 108 | MEMBERS() 109 | # undef MEMBER 110 | } 111 | 112 | inline bool 113 | CameraProperties::serializeWith (Serializer& s) 114 | { 115 | # define MEMBER(Name) \ 116 | report_false_unless("cannot archive camera properties member: " #Name, s.put(Name)); 117 | MEMBERS() 118 | # undef MEMBER 119 | 120 | return true; 121 | } 122 | 123 | # undef MEMBERS 124 | 125 | //------------------------------------------------------------------------------ 126 | 127 | inline 128 | CameraInfo::CameraInfo () 129 | : timestamp(-1.) 130 | , duration(-1) 131 | , calibration() 132 | , properties() 133 | , cmosAndEmitterDistance(NAN) 134 | , referencePlaneDistance(NAN) 135 | , planePixelSize(NAN) 136 | , pixelSizeFactor(-1) 137 | , streamConfig(-1) 138 | , isRegisteredToColor(false) 139 | , unused0(false) 140 | , unused1(false) 141 | , unused2(NAN) 142 | , unused3(NAN) 143 | {} 144 | 145 | inline 146 | CameraInfo::CameraInfo (double timestamp, double duration, CameraCalibration calibration, CameraProperties properties) 147 | : timestamp(timestamp) 148 | , duration(duration) 149 | , calibration(calibration) 150 | , properties(properties) 151 | {} 152 | 153 | # define MEMBERS() \ 154 | MEMBER(timestamp) \ 155 | MEMBER(duration) \ 156 | MEMBER(calibration) \ 157 | MEMBER(properties) \ 158 | MEMBER(cmosAndEmitterDistance) \ 159 | MEMBER(referencePlaneDistance) \ 160 | MEMBER(planePixelSize) \ 161 | MEMBER(pixelSizeFactor) \ 162 | MEMBER(streamConfig) \ 163 | MEMBER(isRegisteredToColor) \ 164 | MEMBER(unused0) \ 165 | MEMBER(unused1) \ 166 | MEMBER(unused2) \ 167 | MEMBER(unused3) 168 | 169 | inline void 170 | CameraInfo::swapWith (CameraInfo& other) 171 | { 172 | # define MEMBER(Name) \ 173 | uplink_swap(Name, other.Name); 174 | MEMBERS() 175 | # undef MEMBER 176 | } 177 | 178 | inline bool 179 | CameraInfo::serializeWith (Serializer& s) 180 | { 181 | # define MEMBER(Name) \ 182 | report_false_unless("cannot archive camera info member: " #Name, s.put(Name)); 183 | MEMBERS() 184 | # undef MEMBER 185 | 186 | return true; 187 | } 188 | 189 | # undef MEMBERS 190 | 191 | //------------------------------------------------------------------------------ 192 | 193 | 194 | } 195 | -------------------------------------------------------------------------------- /headers/camera-fixedparams.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/types.h" 8 | # include "./core/serializers.h" 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | class CameraFixedParams : public Message 15 | { 16 | public: 17 | UPLINK_MESSAGE_CLASS(CameraFixedParams); 18 | 19 | public: 20 | CameraFixedParams (); 21 | 22 | public: 23 | void swapWith (CameraFixedParams& other); 24 | 25 | public: 26 | bool isValid () const; 27 | 28 | public: 29 | bool serializeWith (Serializer& serializer); 30 | 31 | public: 32 | float CMOSAndEmitterDistance; 33 | float refPlaneDistance; 34 | float planePixelSize; 35 | }; 36 | 37 | //------------------------------------------------------------------------------ 38 | 39 | } 40 | 41 | # include "./camera-fixedparams.hpp" 42 | -------------------------------------------------------------------------------- /headers/camera-fixedparams.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./camera-fixedparams.h" 8 | # include "./core/macros.h" 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | inline 15 | CameraFixedParams::CameraFixedParams () 16 | : CMOSAndEmitterDistance(-1) 17 | , refPlaneDistance(-1) 18 | , planePixelSize(-1) 19 | {} 20 | 21 | inline bool 22 | CameraFixedParams::isValid () const 23 | { 24 | return CMOSAndEmitterDistance > 0.f; 25 | } 26 | 27 | inline bool 28 | CameraFixedParams::serializeWith (Serializer& s) 29 | { 30 | # define MEMBER(Name) \ 31 | report_false_unless("cannot archive camera fixed params " #Name, s.put(Name)) 32 | 33 | MEMBER(CMOSAndEmitterDistance); 34 | MEMBER(refPlaneDistance); 35 | MEMBER(planePixelSize); 36 | 37 | # undef MEMBER 38 | 39 | return true; 40 | } 41 | 42 | inline void 43 | CameraFixedParams::swapWith (CameraFixedParams& other) 44 | { 45 | Message::swapWith(other); 46 | 47 | # define MEMBER(Name) \ 48 | uplink_swap(Name, other.Name); 49 | 50 | MEMBER(CMOSAndEmitterDistance); 51 | MEMBER(refPlaneDistance); 52 | MEMBER(planePixelSize); 53 | 54 | # undef MEMBER 55 | } 56 | 57 | //------------------------------------------------------------------------------ 58 | 59 | } 60 | -------------------------------------------------------------------------------- /headers/camera-frame.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./image.h" 8 | # include "./camera-calibration.h" 9 | # include "./camera-fixedparams.h" 10 | 11 | namespace uplink { 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | struct CameraFrame : Message 16 | { 17 | UPLINK_MESSAGE_CLASS(CameraFrame); 18 | 19 | virtual bool serializeWith (Serializer& s) 20 | { 21 | if (s.isWriter()) 22 | { 23 | Writer& w = s.asWriter(); 24 | 25 | report_false_unless("Cannot write RGBD frame depth", w.write(depthImage)); 26 | report_false_unless("Cannot write RGBD frame color", w.write(colorImage)); 27 | } 28 | else 29 | { 30 | Reader& r = s.asReader(); 31 | 32 | report_false_unless("Cannot read RGBD frame depth", r.read(depthImage)); 33 | report_false_unless("Cannot read RGBD frame color", r.read(colorImage)); 34 | } 35 | 36 | return true; 37 | } 38 | 39 | void swapWith (CameraFrame& other) 40 | { 41 | Message::swapWith(other); 42 | 43 | depthImage.swapWith(other.depthImage); 44 | colorImage.swapWith(other.colorImage); 45 | } 46 | 47 | Image depthImage; 48 | Image colorImage; 49 | }; 50 | 51 | //------------------------------------------------------------------------------ 52 | 53 | } 54 | 55 | # include "./camera-frame.hpp" 56 | -------------------------------------------------------------------------------- /headers/camera-frame.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./camera-frame.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | } 18 | -------------------------------------------------------------------------------- /headers/camera-pose.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/types.h" 8 | # include "./core/serializers.h" 9 | 10 | #if UPLINK_HAS_EIGEN 11 | # include 12 | #endif 13 | 14 | namespace uplink { 15 | 16 | //------------------------------------------------------------------------------ 17 | 18 | // Row-major fixed size matrix. Uses the Uplink prefix to avoid name collisions 19 | // with other libraries likely to use FixedSizeMatrix. 20 | template 21 | struct UplinkFixedSizeMatrix : public Serializable 22 | { 23 | public: 24 | UplinkFixedSizeMatrix (T defaultValue = 0) { std::fill (values, values + Rows*Cols, defaultValue); } 25 | 26 | public: 27 | void swapWith (UplinkFixedSizeMatrix& other); 28 | 29 | public: 30 | bool serializeWith (Serializer& serializer); 31 | 32 | public: 33 | T values[Rows*Cols]; 34 | }; 35 | 36 | typedef UplinkFixedSizeMatrix UplinkMatrix6x6f; 37 | 38 | //------------------------------------------------------------------------------ 39 | 40 | class CameraPose : public Message 41 | { 42 | public: 43 | UPLINK_MESSAGE_CLASS(CameraPose) 44 | 45 | public: 46 | enum CameraPoseStatusCode 47 | { 48 | CameraPoseSuccess = 0, 49 | CameraPoseFailed = 1, 50 | CameraPoseDodgy = 2, 51 | CameraPoseBad = 3, 52 | }; 53 | 54 | public: 55 | CameraPose (); 56 | 57 | public: 58 | void swapWith (CameraPose& other); 59 | 60 | public: 61 | bool serializeWith (Serializer& serializer); 62 | 63 | public: 64 | bool isValid () const { return timestamp > -1e-5; } 65 | 66 | public: 67 | float rx, ry, rz; // 3-2-1 euler angles in degrees. 68 | float tx, ty, tz; 69 | UplinkMatrix6x6f covarianceRt; // 6x6 covariance matrix. (0,0) is var(rx). 70 | int statusCode; 71 | double timestamp; 72 | }; 73 | 74 | //------------------------------------------------------------------------------ 75 | 76 | #if UPLINK_HAS_EIGEN 77 | inline void uplinkCameraPoseToMatrix (const uplink::CameraPose& cameraPose, Eigen::Matrix4f& matrixRt); 78 | inline void matrixToUplinkCameraPose (const Eigen::Matrix4f& matrixRt, uplink::CameraPose& cameraPose); 79 | inline uplink::CameraPose toUplink (const Eigen::Isometry3f& cameraRt, double timestamp); 80 | inline Eigen::Isometry3f toIsometry3f (const uplink::CameraPose& cameraPose); 81 | #endif 82 | 83 | } 84 | 85 | # include "./camera-pose.hpp" 86 | -------------------------------------------------------------------------------- /headers/camera-pose.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./camera-pose.h" 8 | # include "./core/macros.h" 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | template 15 | inline void 16 | UplinkFixedSizeMatrix :: swapWith (UplinkFixedSizeMatrix& other) 17 | { 18 | for (int i = 0; i < Rows*Cols; ++i) 19 | uplink_swap(values[i], other.values[i]); 20 | } 21 | 22 | template 23 | inline bool 24 | UplinkFixedSizeMatrix :: serializeWith (Serializer& serializer) 25 | { 26 | bool ok = serializer.putBytes (reinterpret_cast(values), sizeof(values)); 27 | report_false_unless ("cannot archive fixed size matrix", ok); 28 | return true; 29 | } 30 | 31 | //------------------------------------------------------------------------------ 32 | 33 | # define MEMBERS() \ 34 | MEMBER(rx) \ 35 | MEMBER(ry) \ 36 | MEMBER(rz) \ 37 | MEMBER(tx) \ 38 | MEMBER(ty) \ 39 | MEMBER(tz) \ 40 | MEMBER(covarianceRt) \ 41 | MEMBER(statusCode) \ 42 | MEMBER(timestamp) 43 | 44 | inline 45 | CameraPose::CameraPose () 46 | : Message() 47 | # define MEMBER(Name) \ 48 | , Name(0) 49 | MEMBERS() 50 | # undef MEMBER 51 | { 52 | // Mark is as invalid. 53 | timestamp = -1.0; 54 | statusCode = CameraPoseFailed; 55 | } 56 | 57 | inline void 58 | CameraPose::swapWith (CameraPose& other) 59 | { 60 | Message::swapWith(other); 61 | 62 | # define MEMBER(Name) \ 63 | uplink_swap(Name, other.Name); 64 | MEMBERS() 65 | # undef MEMBER 66 | } 67 | 68 | inline bool 69 | CameraPose::serializeWith (Serializer& s) 70 | { 71 | # define MEMBER(Name) \ 72 | report_false_unless("cannot archive camera pose " #Name, s.put(Name)); 73 | MEMBERS() 74 | # undef MEMBER 75 | 76 | return true; 77 | } 78 | 79 | # undef MEMBERS 80 | 81 | //------------------------------------------------------------------------------ 82 | 83 | #if UPLINK_HAS_EIGEN 84 | 85 | inline void uplinkCameraPoseToMatrix (const uplink::CameraPose& cameraPose, Eigen::Matrix4f& matrixRt) 86 | { 87 | Eigen::Isometry3f rbtGuess = Eigen::Isometry3f::Identity(); 88 | Eigen::Vector3f translation; 89 | translation << cameraPose.tx, cameraPose.ty, cameraPose.tz; 90 | 91 | // TODO: Euler angles are not ideal. A real implementation should be over SO3. 92 | Eigen::Matrix3f rotation; 93 | rotation = Eigen::AngleAxisf(cameraPose.rz*DEG2RAD, Eigen::Vector3f::UnitZ()) 94 | * Eigen::AngleAxisf(cameraPose.ry*DEG2RAD, Eigen::Vector3f::UnitY()) 95 | * Eigen::AngleAxisf(cameraPose.rx*DEG2RAD, Eigen::Vector3f::UnitX()); 96 | 97 | rbtGuess.translate(translation); 98 | rbtGuess.rotate(rotation); 99 | matrixRt = rbtGuess.matrix (); 100 | } 101 | 102 | inline void matrixToUplinkCameraPose (const Eigen::Matrix4f& matrixRt, uplink::CameraPose& cameraPose) 103 | { 104 | const Eigen::Matrix3f& R = matrixRt.block<3,3>(0,0); 105 | 106 | // Heading 107 | float h = atan2(R(1,0), R(0,0)); 108 | 109 | // Compute cos & sin of heading 110 | float ch = cos(h); 111 | float sh = sin(h); 112 | 113 | //Pitch 114 | float p = atan2(-R(2,0), R(0,0)*ch + R(1,0)*sh); 115 | 116 | // Roll 117 | float r = atan2(R(0,2)*sh - R(1,2)*ch, -R(0,1)*sh + R(1,1)*ch); 118 | 119 | Eigen::Vector3f euler; 120 | euler << r*RAD2DEG, p*RAD2DEG, h*RAD2DEG; 121 | 122 | cameraPose.rx = euler[0]; 123 | cameraPose.ry = euler[1]; 124 | cameraPose.rz = euler[2]; 125 | cameraPose.tx = matrixRt(0,3); 126 | cameraPose.ty = matrixRt(1,3); 127 | cameraPose.tz = matrixRt(2,3); 128 | } 129 | 130 | inline uplink::CameraPose toUplink (const Eigen::Isometry3f& cameraRt, double timestamp) 131 | { 132 | uplink::CameraPose output; 133 | output.timestamp = timestamp; 134 | matrixToUplinkCameraPose(cameraRt.matrix(), output); 135 | return output; 136 | } 137 | 138 | inline Eigen::Isometry3f toIsometry3f (const uplink::CameraPose& cameraPose) 139 | { 140 | Eigen::Isometry3f output; 141 | uplinkCameraPoseToMatrix(cameraPose, output.matrix()); 142 | return output; 143 | } 144 | 145 | #endif // UPLINK_HAS_EIGEN 146 | 147 | //------------------------------------------------------------------------------ 148 | 149 | } 150 | -------------------------------------------------------------------------------- /headers/clients.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./endpoints.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | struct ClientEndpoint : Endpoint 14 | { 15 | virtual void onVersionInfo (const VersionInfo& clientVersionInfo); 16 | virtual void onSessionSetup(const uplink::SessionSetup &sessionSetup); 17 | virtual bool setupSession (const SessionSettings& nextSessionSettings) = 0; 18 | virtual void reset (); 19 | 20 | virtual void onSessionSetupSuccess () = 0; 21 | virtual void onSessionSetupFailure () = 0; 22 | 23 | virtual void onSessionSetupReply (const SessionSetupReply&) 24 | { 25 | // Nothing to do. 26 | 27 | // FIXME: Report. We're not supposed to receive that server-side-only message. 28 | } 29 | }; 30 | 31 | //------------------------------------------------------------------------------ 32 | 33 | } 34 | 35 | # include "./clients.hpp" 36 | -------------------------------------------------------------------------------- /headers/clients.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./clients.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | inline void 14 | ClientEndpoint::onVersionInfo (const VersionInfo& clientVersionInfo) 15 | { 16 | uplink_log_info("Server version: %i.%i", clientVersionInfo.major, clientVersionInfo.minor); 17 | 18 | // Nothing else to do, for now. 19 | } 20 | 21 | inline void 22 | ClientEndpoint::onSessionSetup(const uplink::SessionSetup &sessionSetup) 23 | { 24 | SessionSettings nextSessionSettings = currentSessionSettings; 25 | 26 | if (!sessionSetup.applyTo(nextSessionSettings)) 27 | return; // Session settings did not change. 28 | 29 | if (!setupSession(nextSessionSettings)) 30 | { 31 | onSessionSetupFailure(); 32 | 33 | sendSessionSetupReply(SessionSetupReply(InvalidSessionId, SessionSetupStatus_Failure)); 34 | 35 | uplink_log_error("Session setup failed."); 36 | } 37 | else 38 | { 39 | static unsigned sessionCounter = 0; 40 | 41 | // Next messages will be sent and received as part of the new session. 42 | // FIXME: Let the remote side choose the id and return that. 43 | currentSessionId = FirstSessionId + sessionCounter++; 44 | 45 | currentSessionSettings = nextSessionSettings; 46 | 47 | sendSessionSetupReply(SessionSetupReply(currentSessionId, SessionSetupStatus_Success)); 48 | 49 | onSessionSetupSuccess(); 50 | 51 | uplink_log_info("Session setup succeeded."); 52 | } 53 | } 54 | 55 | inline bool 56 | ClientEndpoint::setupSession (const SessionSettings& nextSessionSettings) 57 | { 58 | setAllChannelSettings(nextSessionSettings); 59 | 60 | return true; 61 | } 62 | 63 | inline void 64 | ClientEndpoint::reset () 65 | { 66 | Endpoint::reset(); 67 | 68 | currentSessionSettings.clear(); 69 | 70 | uplink_log_debug("Client endpoint reset."); 71 | } 72 | 73 | //------------------------------------------------------------------------------ 74 | 75 | } 76 | -------------------------------------------------------------------------------- /headers/context.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/platform.h" 8 | # include "./core/threads.h" 9 | # include 10 | 11 | namespace uplink { 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | class Context 16 | { 17 | public: 18 | Context () 19 | : _profiler(0) 20 | { 21 | platform_startup(); 22 | } 23 | 24 | public: 25 | ~Context () 26 | { 27 | zero_delete(_profiler); 28 | 29 | platform_shutdown(); 30 | } 31 | 32 | public: 33 | Profiler* profiler () { return _profiler; } 34 | 35 | void setProfiler (Profiler* profiler_) 36 | { 37 | assert(0 == _profiler); // Call this once only. 38 | 39 | assert(0 != profiler_); 40 | 41 | _profiler = profiler_; 42 | 43 | _profiler->registerTasks(); 44 | } 45 | 46 | public: 47 | void log_line (Verbosity verbosity, CString message) 48 | { 49 | const MutexLocker _(_logging); 50 | 51 | // FIXME: Timestamps. 52 | // FIXME: Remote log. 53 | // FIXME: Verbosity filter. 54 | 55 | console_log_line(verbosity, message); 56 | } 57 | 58 | private: 59 | Profiler* _profiler; 60 | Mutex _logging; 61 | }; 62 | 63 | //------------------------------------------------------------------------------ 64 | 65 | // The context singleton instance is defined uniquely in: 66 | // 67 | // uplink.cpp (C++), 68 | // uplink.mm (Objective C++). 69 | 70 | extern Context context; 71 | 72 | //------------------------------------------------------------------------------ 73 | 74 | // Callbacks 75 | 76 | inline void 77 | profiler_task_started (ProfilerTask task) 78 | { 79 | Profiler* const profiler = context.profiler(); 80 | 81 | if (0 == profiler) 82 | return; 83 | 84 | profiler->taskStarted(profiler->taskIds[task]); 85 | } 86 | 87 | inline void 88 | profiler_task_stopped (ProfilerTask task) 89 | { 90 | Profiler* const profiler = context.profiler(); 91 | 92 | if (0 == profiler) 93 | return; 94 | 95 | profiler->taskStopped(profiler->taskIds[task]); 96 | } 97 | 98 | inline void 99 | log_line (Verbosity verbosity, CString message) 100 | { 101 | context.log_line(verbosity, message); 102 | } 103 | 104 | } 105 | 106 | # include "./context.hpp" 107 | -------------------------------------------------------------------------------- /headers/context.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./context.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | } 16 | -------------------------------------------------------------------------------- /headers/core/bitstream.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include 8 | # include 9 | # include 10 | 11 | # define BITSTREAM_SUCCESS 1 12 | # define BITSTREAM_FAILURE 0 13 | 14 | namespace uplink { 15 | 16 | //------------------------------------------------------------------------------ 17 | 18 | typedef struct s_bitstream { 19 | uint8_t *buf; /* head of bitstream */ 20 | uint8_t *pos; /* current byte in bitstream */ 21 | unsigned int remain; /* bits remaining */ 22 | unsigned int len; /* length of bitstream in bytes */ 23 | uint8_t cur_bits; 24 | } bitstream_t; 25 | 26 | int bs_init(bitstream_t *bp); 27 | int bs_destroy(bitstream_t **ppb); 28 | int bs_attach(bitstream_t *b, uint8_t *buf, int blen); 29 | uint8_t bs_get(bitstream_t * b, uint8_t nbits); 30 | int bs_bytes_used(bitstream_t *b); 31 | 32 | static inline int 33 | bs_put(bitstream_t * b, 34 | uint8_t bits, 35 | uint8_t nbits) 36 | { 37 | assert(nbits != 0 && nbits <= 8); 38 | 39 | if ( nbits > b->remain ) { 40 | unsigned int over = nbits - b->remain; 41 | *(b->pos++) = b->cur_bits | (bits >> over); 42 | b->remain = 8 - over; 43 | b->cur_bits = bits << b->remain; 44 | } else { 45 | b->cur_bits |= bits << (b->remain - nbits); 46 | b->remain -= nbits; 47 | 48 | // we've exhausted the byte. move to the next byte. 49 | if (b->remain == 0) { 50 | *(b->pos++) = b->cur_bits; 51 | b->remain = 8; 52 | b->cur_bits = 0; 53 | } 54 | } 55 | 56 | assert((unsigned int)(b->pos - b->buf) <= b->len); 57 | return BITSTREAM_SUCCESS; 58 | } 59 | 60 | static inline int 61 | bs_flush(bitstream_t * b) 62 | { 63 | *(b->pos) = b->cur_bits; 64 | return BITSTREAM_SUCCESS; 65 | } 66 | 67 | //------------------------------------------------------------------------------ 68 | 69 | } 70 | 71 | # include "bitstream.hpp" 72 | -------------------------------------------------------------------------------- /headers/core/bitstream.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | // Adapted from code originally written by Orion Hodson. 6 | // 7 | // See: https://github.com/uclmediatools/rat/blob/master/bitstream.c 8 | // 9 | // Key changes: 10 | // - Performance 11 | // - Use of temporary uint8_t (during write) 12 | // TODOs: 13 | // - Temporary char should be used during read too. 14 | // 15 | 16 | # pragma once 17 | 18 | # include "./bitstream.h" 19 | # include 20 | # include 21 | # include 22 | # include 23 | # include 24 | 25 | namespace uplink { 26 | 27 | //------------------------------------------------------------------------------ 28 | 29 | inline int 30 | bs_init(bitstream_t *bp) 31 | { 32 | if (bp) { 33 | memset(bp, 0, sizeof(bitstream_t)); 34 | return BITSTREAM_SUCCESS; 35 | } 36 | return BITSTREAM_FAILURE; 37 | } 38 | 39 | inline int 40 | bs_destroy(bitstream_t * b) 41 | { 42 | free(b); 43 | return BITSTREAM_SUCCESS; 44 | } 45 | 46 | inline int 47 | bs_attach(bitstream_t *b, 48 | uint8_t *buf, 49 | int blen) 50 | { 51 | b->buf = b->pos = buf; 52 | b->remain = 8; 53 | b->len = blen; 54 | return BITSTREAM_SUCCESS; 55 | } 56 | 57 | inline int 58 | bs_bytes_used(bitstream_t *b) 59 | { 60 | unsigned int used = (unsigned int)(b->pos - b->buf); 61 | return b->remain != 8 ? used + 1 : used; 62 | } 63 | 64 | inline uint8_t 65 | bs_get(bitstream_t * b, 66 | uint8_t nbits) 67 | { 68 | uint8_t out; 69 | 70 | if (b->remain == 0) { 71 | b->pos++; 72 | b->remain = 8; 73 | } 74 | 75 | if (nbits > b->remain) { 76 | /* Get high bits */ 77 | out = *b->pos; 78 | out <<= (8 - b->remain); 79 | out >>= (8 - nbits); 80 | b->pos++; 81 | b->remain += 8 - nbits; 82 | out |= (*b->pos) >> b->remain; 83 | } else { 84 | out = *b->pos; 85 | out <<= (8 - b->remain); 86 | out >>= (8 - nbits); 87 | b->remain -= nbits; 88 | } 89 | 90 | assert((unsigned int)(b->pos - b->buf) <= b->len); 91 | return out; 92 | } 93 | 94 | //------------------------------------------------------------------------------ 95 | 96 | } 97 | -------------------------------------------------------------------------------- /headers/core/bytes.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./types.h" 8 | # include 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | // In the remainder of this file, bytes are numbered using indices of increasing significance. 15 | // As such, 0 is always the least significant byte. 16 | 17 | template < unsigned > struct Nth {}; 18 | 19 | //------------------------------------------------------------------------------ 20 | 21 | inline Byte getByte (Nth<0>, uint16 val) { return Byte( val & 0x00FF ); } 22 | inline Byte getByte (Nth<1>, uint16 val) { return Byte((val & 0xFF00) >> 8 ); } 23 | 24 | inline Byte getByte (Nth<0>, uint32 val) { return Byte( val & 0x000000FF ); } 25 | inline Byte getByte (Nth<1>, uint32 val) { return Byte((val & 0x0000FF00) >> 8 ); } 26 | inline Byte getByte (Nth<2>, uint32 val) { return Byte((val & 0x00FF0000) >> 16); } 27 | inline Byte getByte (Nth<3>, uint32 val) { return Byte((val & 0xFF000000) >> 24); } 28 | 29 | inline Byte getByte (Nth<0>, uint64 val) { return Byte( val & 0x00000000000000FF ); } 30 | inline Byte getByte (Nth<1>, uint64 val) { return Byte((val & 0x000000000000FF00) >> 8 ); } 31 | inline Byte getByte (Nth<2>, uint64 val) { return Byte((val & 0x0000000000FF0000) >> 16); } 32 | inline Byte getByte (Nth<3>, uint64 val) { return Byte((val & 0x00000000FF000000) >> 24); } 33 | inline Byte getByte (Nth<4>, uint64 val) { return Byte((val & 0x000000FF00000000) >> 32); } 34 | inline Byte getByte (Nth<5>, uint64 val) { return Byte((val & 0x0000FF0000000000) >> 40); } 35 | inline Byte getByte (Nth<6>, uint64 val) { return Byte((val & 0x00FF000000000000) >> 48); } 36 | inline Byte getByte (Nth<7>, uint64 val) { return Byte((val & 0xFF00000000000000) >> 56); } 37 | 38 | template < unsigned Index > inline Byte getByte (uint16 val) { return getByte(Nth(), val); } 39 | template < unsigned Index > inline Byte getByte (uint32 val) { return getByte(Nth(), val); } 40 | template < unsigned Index > inline Byte getByte (uint64 val) { return getByte(Nth(), val); } 41 | 42 | //------------------------------------------------------------------------------ 43 | 44 | inline void setByte (Nth<0>, Byte byte, uint16& val) { val = (val & 0xFF00) | uint16(byte) ; } 45 | inline void setByte (Nth<1>, Byte byte, uint16& val) { val = (val & 0x00FF) | (uint16(byte) << 8 ); } 46 | 47 | inline void setByte (Nth<0>, Byte byte, uint32& val) { val = (val & 0xFFFFFF00) | uint32(byte) ; } 48 | inline void setByte (Nth<1>, Byte byte, uint32& val) { val = (val & 0xFFFF00FF) | (uint32(byte) << 8 ); } 49 | inline void setByte (Nth<2>, Byte byte, uint32& val) { val = (val & 0xFF00FFFF) | (uint32(byte) << 16); } 50 | inline void setByte (Nth<3>, Byte byte, uint32& val) { val = (val & 0x00FFFFFF) | (uint32(byte) << 24); } 51 | 52 | inline void setByte (Nth<0>, Byte byte, uint64& val) { val = (val & 0xFFFFFFFFFFFFFF00) | uint64(byte) ; } 53 | inline void setByte (Nth<1>, Byte byte, uint64& val) { val = (val & 0xFFFFFFFFFFFF00FF) | (uint64(byte) << 8 ); } 54 | inline void setByte (Nth<2>, Byte byte, uint64& val) { val = (val & 0xFFFFFFFFFF00FFFF) | (uint64(byte) << 16); } 55 | inline void setByte (Nth<3>, Byte byte, uint64& val) { val = (val & 0xFFFFFFFF00FFFFFF) | (uint64(byte) << 24); } 56 | inline void setByte (Nth<4>, Byte byte, uint64& val) { val = (val & 0xFFFFFF00FFFFFFFF) | (uint64(byte) << 32); } 57 | inline void setByte (Nth<5>, Byte byte, uint64& val) { val = (val & 0xFFFF00FFFFFFFFFF) | (uint64(byte) << 40); } 58 | inline void setByte (Nth<6>, Byte byte, uint64& val) { val = (val & 0xFF00FFFFFFFFFFFF) | (uint64(byte) << 48); } 59 | inline void setByte (Nth<7>, Byte byte, uint64& val) { val = (val & 0x00FFFFFFFFFFFFFF) | (uint64(byte) << 56); } 60 | 61 | template < unsigned Index > inline void setByte (Byte byte, uint16& val) { setByte(Nth(), byte, val); } 62 | template < unsigned Index > inline void setByte (Byte byte, uint32& val) { setByte(Nth(), byte, val); } 63 | template < unsigned Index > inline void setByte (Byte byte, uint64& val) { setByte(Nth(), byte, val); } 64 | 65 | //------------------------------------------------------------------------------ 66 | 67 | inline uint64 byteOrderSwapped (uint64 val); 68 | inline uint32 byteOrderSwapped (uint32 val); 69 | inline uint16 byteOrderSwapped (uint16 val); 70 | 71 | //------------------------------------------------------------------------------ 72 | 73 | void appendBuffer ( Buffer& buffer, const Byte* bytes, Size size); 74 | Byte* growBuffer ( Buffer& buffer, Size increase); 75 | Byte* mutableBufferBytes ( Buffer& buffer, Index offset = 0); 76 | const Byte* bufferBytes (const Buffer& buffer, Index offset = 0); 77 | 78 | //------------------------------------------------------------------------------ 79 | 80 | } 81 | 82 | #include "bytes.hpp" 83 | -------------------------------------------------------------------------------- /headers/core/bytes.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./bytes.h" 8 | # include 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | inline uint64 15 | byteOrderSwapped (uint64 val) 16 | { 17 | uint64 ret; 18 | 19 | setByte<0>(getByte<7>(val), ret); 20 | setByte<1>(getByte<6>(val), ret); 21 | setByte<2>(getByte<5>(val), ret); 22 | setByte<3>(getByte<4>(val), ret); 23 | setByte<4>(getByte<3>(val), ret); 24 | setByte<5>(getByte<2>(val), ret); 25 | setByte<6>(getByte<1>(val), ret); 26 | setByte<7>(getByte<0>(val), ret); 27 | 28 | return ret; 29 | } 30 | 31 | inline uint32 32 | byteOrderSwapped (uint32 val) 33 | { 34 | uint32 ret; 35 | 36 | setByte<0>(getByte<3>(val), ret); 37 | setByte<1>(getByte<2>(val), ret); 38 | setByte<2>(getByte<1>(val), ret); 39 | setByte<3>(getByte<0>(val), ret); 40 | 41 | return ret; 42 | } 43 | 44 | inline uint16 45 | byteOrderSwapped (uint16 val) 46 | { 47 | uint16 ret; 48 | 49 | setByte<0>(getByte<1>(val), ret); 50 | setByte<1>(getByte<0>(val), ret); 51 | 52 | return ret; 53 | } 54 | 55 | inline void 56 | appendBuffer (Buffer& buffer, const Byte* bytes, Size size) 57 | { 58 | buffer.insert(buffer.end(), bytes, bytes + size); 59 | } 60 | 61 | inline Byte* 62 | growBuffer (Buffer& buffer, Size increase) 63 | { 64 | assert(0 <= increase); 65 | Size at = buffer.size(); 66 | buffer.resize(at + increase); 67 | assert(!buffer.empty()); // Or we cannot return any valid pointer. 68 | return &buffer[at]; 69 | } 70 | 71 | inline Byte* 72 | mutableBufferBytes (Buffer& buffer, Index offset) 73 | { 74 | assert(size_t(offset) < buffer.size()); 75 | 76 | return &buffer[offset]; 77 | } 78 | 79 | inline const Byte* 80 | bufferBytes (const Buffer& buffer, Index offset) 81 | { 82 | return mutableBufferBytes(const_cast(buffer), offset); 83 | } 84 | 85 | //------------------------------------------------------------------------------ 86 | 87 | } 88 | -------------------------------------------------------------------------------- /headers/core/chunks.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | // This file was intentionally written using some wide text lines. 6 | // Please keep it this way. 7 | 8 | # pragma once 9 | 10 | # include "./bytes.h" 11 | # include "./streams.h" 12 | # include "./serializers.h" 13 | # include 14 | 15 | namespace uplink { 16 | 17 | //------------------------------------------------------------------------------ 18 | 19 | struct Chunk 20 | { 21 | // Fixed-sized data segment. 22 | 23 | public: 24 | Chunk () {} 25 | virtual ~Chunk () {} 26 | 27 | public: 28 | virtual Size chunkSize () const = 0; 29 | virtual void storeChunk ( Byte*& bytes) const = 0; 30 | virtual void fetchChunk (const Byte*& bytes) = 0; 31 | 32 | public: 33 | Byte* appendTo ( Buffer& buffer) const; 34 | void fetchFrom (const Buffer& buffer, Index at = 0); 35 | void fetchFrom (const Byte* bytes); 36 | }; 37 | 38 | //------------------------------------------------------------------------------ 39 | 40 | class Fields : public Chunk 41 | { 42 | public: 43 | Fields (); 44 | virtual ~Fields (); 45 | 46 | public: // Chunk 47 | virtual Size chunkSize () const; 48 | virtual void storeChunk ( Byte*& bytes) const; 49 | virtual void fetchChunk (const Byte*& bytes); 50 | 51 | # define UPLINK_SERIALIZER_ATOM(Name, Type) \ 52 | private: \ 53 | struct Name##Atom : Chunk \ 54 | { \ 55 | Name##Atom (Type* instance) : instance(instance) { assert(instance != 0); } \ 56 | \ 57 | virtual Size chunkSize () const { return sizeof(Type); } \ 58 | virtual void storeChunk ( Byte*& bytes) const { store(*instance, bytes); } \ 59 | virtual void fetchChunk (const Byte*& bytes) { fetch(*instance, bytes); } \ 60 | \ 61 | Type* instance; \ 62 | }; \ 63 | public: \ 64 | void addChunk (Type* instance) { addChunk(new Name##Atom(instance), true); } 65 | UPLINK_SERIALIZER_ATOMS() 66 | # undef UPLINK_SERIALIZER_ATOM 67 | 68 | public: 69 | void addChunk (Chunk* chunk, bool own = false) 70 | { 71 | chunks.push_back(chunk); 72 | 73 | size += chunks.back()->chunkSize(); 74 | 75 | if (own) 76 | owned.push_back(chunk); 77 | } 78 | 79 | private: 80 | typedef std::vector Chunks; 81 | 82 | private: 83 | Size size; 84 | Chunks chunks; 85 | Chunks owned; 86 | }; 87 | 88 | //------------------------------------------------------------------------------ 89 | 90 | struct Header : Chunk 91 | { 92 | public: 93 | Header (Size magicSize) : magic() { magic.resize(magicSize, '\0'); } 94 | Header (CString magic) : magic(magic) {} 95 | virtual ~Header () {} 96 | 97 | public: // Chunk 98 | virtual Size chunkSize () const; 99 | virtual void storeChunk ( Byte*& bytes) const; 100 | virtual void fetchChunk (const Byte*& bytes); 101 | 102 | public: 103 | String magic ; 104 | Fields fields; 105 | }; 106 | 107 | //------------------------------------------------------------------------------ 108 | 109 | } 110 | 111 | # include "./chunks.hpp" 112 | -------------------------------------------------------------------------------- /headers/core/chunks.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./chunks.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | inline Byte* 14 | Chunk::appendTo (Buffer& buffer) const 15 | { 16 | Byte* ret = growBuffer(buffer, chunkSize()); 17 | Byte* tmp = ret; 18 | storeChunk(tmp); 19 | return ret; 20 | } 21 | 22 | inline void 23 | Chunk::fetchFrom (const Buffer& buffer, Index at) 24 | { 25 | assert(at + chunkSize() <= buffer.size()); 26 | const Byte* bytes = &buffer[at]; 27 | fetchChunk(bytes); 28 | } 29 | 30 | inline void 31 | Chunk::fetchFrom (const Byte* bytes) 32 | { 33 | fetchChunk(bytes); 34 | } 35 | 36 | //------------------------------------------------------------------------------ 37 | 38 | inline 39 | Fields::Fields () 40 | : size(0) 41 | { 42 | 43 | } 44 | 45 | inline 46 | Fields::~Fields () 47 | { 48 | for (int i = 0; i < owned.size(); ++i) 49 | delete owned[i]; 50 | } 51 | 52 | inline Size 53 | Fields::chunkSize () const 54 | { 55 | return size; 56 | } 57 | 58 | inline void 59 | Fields::storeChunk (Byte*& bytes) const 60 | { 61 | for (int i = 0; i < chunks.size(); ++i) 62 | chunks[i]->storeChunk(bytes); 63 | } 64 | 65 | inline void 66 | Fields::fetchChunk (const Byte*& bytes) 67 | { 68 | for (int i = 0; i < chunks.size(); ++i) 69 | chunks[i]->fetchChunk(bytes); 70 | } 71 | 72 | //------------------------------------------------------------------------------ 73 | 74 | inline Size 75 | Header::chunkSize () const 76 | { 77 | return magic.size() + fields.chunkSize(); 78 | } 79 | 80 | inline void 81 | Header::storeChunk (Byte*& bytes) const 82 | { 83 | std::memcpy(bytes, &magic[0], magic.size()); 84 | bytes += magic.size(); 85 | fields.storeChunk(bytes); 86 | } 87 | 88 | inline void 89 | Header::fetchChunk (const Byte*& bytes) 90 | { 91 | magic.assign(CString(bytes), magic.size()); 92 | bytes += magic.size(); 93 | fields.fetchChunk(bytes); 94 | } 95 | 96 | //------------------------------------------------------------------------------ 97 | 98 | } 99 | -------------------------------------------------------------------------------- /headers/core/clocks.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./config.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | inline double 14 | getTime () 15 | { 16 | return double(getTickCount()) / double(getTickFrequency()); 17 | } 18 | 19 | static const double never = std::numeric_limits::lowest(); 20 | 21 | //------------------------------------------------------------------------------ 22 | 23 | class RateEstimator 24 | { 25 | public: 26 | enum { DefaultWindow = 10 }; 27 | 28 | public: 29 | explicit RateEstimator (int window = DefaultWindow); 30 | 31 | public: 32 | void reset (); 33 | void tick (); 34 | 35 | public: 36 | float windowedRate () const; 37 | float instantRate () const; 38 | 39 | public: 40 | String toString () const 41 | { 42 | return formatted_copy("%7.2f Hz", windowedRate()); 43 | } 44 | 45 | private: 46 | int count; 47 | double first; 48 | double last; 49 | int window; 50 | float windowed; 51 | }; 52 | 53 | //------------------------------------------------------------------------------ 54 | 55 | class StopWatch 56 | { 57 | public: 58 | StopWatch () 59 | : startTime(0.) 60 | { 61 | } 62 | 63 | public: 64 | void start () 65 | { 66 | startTime = getTime(); 67 | } 68 | 69 | double elapsed () const 70 | { 71 | return getTime() - startTime; 72 | } 73 | 74 | private: 75 | double startTime; 76 | }; 77 | 78 | //------------------------------------------------------------------------------ 79 | 80 | } 81 | 82 | # include "./clocks.hpp" 83 | -------------------------------------------------------------------------------- /headers/core/clocks.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./clocks.hpp" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | inline 14 | RateEstimator::RateEstimator (int window) 15 | : count(0) 16 | , first(0.) 17 | , last(0.) 18 | , window(window) 19 | , windowed(0.f) 20 | { 21 | assert(0 < window); 22 | } 23 | 24 | inline void 25 | RateEstimator::reset () 26 | { 27 | count = 0; 28 | first = 0.; 29 | last = 0.; 30 | windowed = 0.f; 31 | } 32 | 33 | inline void 34 | RateEstimator::tick () 35 | { 36 | last = double(getTickCount()); 37 | 38 | if (count == 0) 39 | { 40 | first = last; 41 | } 42 | else if (count < window) 43 | { 44 | windowed = float(count) / float((last - first) / getTickFrequency()); 45 | } 46 | else if (count % window == 0) 47 | { 48 | windowed = float(window) / float((last - first) / getTickFrequency()); 49 | 50 | first = last; 51 | } 52 | 53 | ++count; 54 | } 55 | 56 | inline float 57 | RateEstimator::windowedRate () const 58 | { 59 | return windowed; 60 | } 61 | 62 | inline float 63 | RateEstimator::instantRate () const 64 | { 65 | return 1.f / float((getTickCount() - last) / getTickFrequency()); 66 | } 67 | 68 | //------------------------------------------------------------------------------ 69 | 70 | } 71 | -------------------------------------------------------------------------------- /headers/core/config.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | //------------------------------------------------------------------------------ 8 | 9 | // Set this to 1 if you feel like slowing things down a lot and bloating the console with a lot of debugging info. 10 | 11 | # ifndef UPLINK_DEBUG 12 | # define UPLINK_DEBUG 0 13 | # endif 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | // Set this to 1 you are willing to add extra profiling code and pay its performance price tag. 18 | 19 | # ifndef UPLINK_PROFILE 20 | # define UPLINK_PROFILE 0 21 | # endif 22 | 23 | //------------------------------------------------------------------------------ 24 | 25 | // Set this to 1 if you are on windows. Stay away from it otherwise, for now. 26 | 27 | # ifndef UPLINK_HAS_DESKTOP_UI 28 | # define UPLINK_HAS_DESKTOP_UI 1 29 | # endif 30 | 31 | //------------------------------------------------------------------------------ 32 | 33 | // Set this to 1 if you're building Uplink in a context that provides the Eigen library headers. 34 | 35 | # ifndef UPLINK_HAS_EIGEN 36 | # define UPLINK_HAS_EIGEN 0 37 | # endif 38 | 39 | //------------------------------------------------------------------------------ 40 | 41 | // Uplink can serialize primitive types using (big endian) network byte order. 42 | // Since the current set of supported architectures is completely little endian, we use native ordering instead. 43 | // Set this to 0 if you feel adventurous about running Uplink on big endian processors. 44 | 45 | # ifndef UPLINK_SERIALIZERS_USE_HOST_BYTE_ORDER 46 | # define UPLINK_SERIALIZERS_USE_HOST_BYTE_ORDER 1 47 | # endif 48 | -------------------------------------------------------------------------------- /headers/core/datagrams.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./platform.h" 8 | 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace uplink { 12 | 13 | class DatagramBroadcaster 14 | { 15 | public: 16 | DatagramBroadcaster (); 17 | ~DatagramBroadcaster (); 18 | 19 | public: 20 | bool open (int port); 21 | void close (); 22 | bool ready () const; 23 | 24 | public: 25 | bool send (const Byte* bytes, Size length); 26 | bool send (CString); 27 | 28 | private: 29 | UDPBroadcaster* broadcaster; 30 | }; 31 | 32 | //------------------------------------------------------------------------------ 33 | 34 | class DatagramListener 35 | { 36 | public: 37 | DatagramListener (); 38 | ~DatagramListener (); 39 | 40 | public: 41 | bool open (int port); 42 | void close (); 43 | bool ready () const; 44 | 45 | public: 46 | bool receive (Byte* bytes, Size size, NetworkAddress& sender); 47 | 48 | private: 49 | UDPListener* listener; 50 | }; 51 | 52 | } 53 | 54 | # include "./datagrams.hpp" 55 | -------------------------------------------------------------------------------- /headers/core/datagrams.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./datagrams.h" 8 | # include "./macros.h" 9 | # include "./platform.h" 10 | # include 11 | 12 | namespace uplink { 13 | 14 | //------------------------------------------------------------------------------ 15 | 16 | inline String 17 | NetworkAddress::toString () const 18 | { 19 | return formatted_copy("%d.%d.%d.%d", ipv4[3], ipv4[2], ipv4[1], ipv4[0]); 20 | } 21 | 22 | inline void 23 | NetworkAddress::operator = (uint32_t ipv4_addr) 24 | { 25 | ipv4[0] = (ipv4_addr & 0xFF000000) >> 24; 26 | ipv4[1] = (ipv4_addr & 0x00FF0000) >> 16; 27 | ipv4[2] = (ipv4_addr & 0x0000FF00) >> 8 ; 28 | ipv4[3] = (ipv4_addr & 0x000000FF) ; 29 | } 30 | 31 | inline std::ostream& 32 | operator << (std::ostream& o, const NetworkAddress& addr) 33 | { 34 | return o << addr.toString(); 35 | } 36 | 37 | //------------------------------------------------------------------------------ 38 | 39 | inline 40 | DatagramBroadcaster::DatagramBroadcaster () 41 | : broadcaster(0) 42 | { 43 | 44 | } 45 | 46 | inline 47 | DatagramBroadcaster::~DatagramBroadcaster () 48 | { 49 | close(); 50 | } 51 | 52 | inline bool 53 | DatagramBroadcaster::open (int port) 54 | { 55 | if (ready()) 56 | close(); 57 | 58 | broadcaster = UDPBroadcaster_create(port); 59 | 60 | return 0 != broadcaster; 61 | } 62 | 63 | inline void 64 | DatagramBroadcaster::close () 65 | { 66 | if (!ready()) 67 | return; 68 | 69 | zero_delete(broadcaster); 70 | } 71 | 72 | inline bool 73 | DatagramBroadcaster::ready () const 74 | { 75 | return 0 != broadcaster; 76 | } 77 | 78 | inline bool 79 | DatagramBroadcaster::send (const Byte* bytes, Size length) 80 | { 81 | assert(ready()); 82 | 83 | return broadcaster->broadcast(bytes, length); 84 | } 85 | 86 | inline bool 87 | DatagramBroadcaster::send (CString message) 88 | { 89 | assert(0 != message); 90 | 91 | const size_t length = strlen(message); 92 | 93 | return send(reinterpret_cast(message), length); 94 | } 95 | 96 | //------------------------------------------------------------------------------ 97 | 98 | inline 99 | DatagramListener::DatagramListener () 100 | : listener(0) 101 | { 102 | 103 | } 104 | 105 | inline 106 | DatagramListener::~DatagramListener () 107 | { 108 | close(); 109 | } 110 | 111 | inline bool 112 | DatagramListener::open (int port) 113 | { 114 | if (ready()) 115 | close(); 116 | 117 | listener = UDPListener_create(port); 118 | 119 | return 0 != listener; 120 | } 121 | 122 | inline void 123 | DatagramListener::close () 124 | { 125 | if (!ready()) 126 | return; 127 | 128 | zero_delete(listener); 129 | } 130 | 131 | inline bool 132 | DatagramListener::ready () const 133 | { 134 | return 0 != listener; 135 | } 136 | 137 | inline bool 138 | DatagramListener::receive (Byte* bytes, Size size, NetworkAddress& sender) 139 | { 140 | assert(0 != listener); 141 | 142 | return listener->receive(bytes, size, sender); 143 | } 144 | 145 | //------------------------------------------------------------------------------ 146 | 147 | } 148 | -------------------------------------------------------------------------------- /headers/core/enum.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./chunks.h" 8 | # include "./serializers.h" 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | template < typename Type, Type Invalid, Type HowMany > 15 | struct Enum : Serializable, Chunk 16 | { 17 | typedef uint32 Unsigned; // FIXME: 4 bytes is too big. 18 | 19 | Enum (); 20 | Enum (Type value); 21 | 22 | operator const Type () const; 23 | 24 | Enum& operator = (const Type& rhs); 25 | 26 | void swapWith (Enum& other); 27 | 28 | virtual bool serializeWith (Serializer& serializer); 29 | 30 | virtual Size chunkSize () const; 31 | virtual void storeChunk ( Byte*& bytes) const; 32 | virtual void fetchChunk (const Byte*& bytes); 33 | 34 | bool operator == (const Enum& rhs) const; 35 | bool operator != (const Enum& rhs) const; 36 | 37 | bool operator != (const Type& otherValue) const; 38 | bool operator == (const Type& otherValue) const; 39 | 40 | String toString () const 41 | { 42 | return ::uplink::toString(int(value)); // For now. FIXME: Return enum names instead. 43 | } 44 | 45 | Type value; 46 | }; 47 | 48 | //------------------------------------------------------------------------------ 49 | 50 | template < typename Type, Type Invalid, Type HowMany > 51 | inline bool 52 | operator == (const Type& value, const Enum& that); 53 | 54 | template < typename Type, Type Invalid, Type HowMany > 55 | inline bool 56 | operator != (const Type& value, const Enum& that); 57 | 58 | //------------------------------------------------------------------------------ 59 | 60 | #define UPLINK_ENUM_BEGIN(Name) \ 61 | enum Name##_Enum \ 62 | { \ 63 | Name##_Invalid = -1, \ 64 | 65 | #define UPLINK_ENUM_END(Name) \ 66 | Name##_HowMany \ 67 | }; \ 68 | typedef Enum Name; 69 | 70 | //------------------------------------------------------------------------------ 71 | 72 | } 73 | 74 | # include "./enum.hpp" 75 | -------------------------------------------------------------------------------- /headers/core/enum.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./enum.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | # define ENUM_METHOD(...) \ 14 | template < typename Type, Type Invalid, Type HowMany > \ 15 | inline __VA_ARGS__ \ 16 | Enum:: 17 | 18 | ENUM_METHOD() 19 | Enum () 20 | : value(Invalid) 21 | { 22 | } 23 | 24 | ENUM_METHOD() 25 | Enum (Type value) 26 | : value(value) 27 | { 28 | } 29 | 30 | ENUM_METHOD() 31 | operator const Type () const 32 | { 33 | return value; 34 | } 35 | 36 | ENUM_METHOD(Enum&) 37 | operator = (const Type& rhs) 38 | { 39 | value = rhs; return *this; 40 | } 41 | 42 | ENUM_METHOD(void) 43 | swapWith (Enum& other) 44 | { 45 | ::std::swap(value, other.value); 46 | } 47 | 48 | ENUM_METHOD(bool) 49 | serializeWith (Serializer& serializer) 50 | { 51 | Unsigned n = 0; 52 | 53 | if (serializer.isWriter()) 54 | { 55 | return_false_unless(Invalid < value && value < HowMany); 56 | 57 | n = value; 58 | } 59 | 60 | return_false_unless(serializer.put(n)); 61 | 62 | if (serializer.isReader()) 63 | { 64 | return_false_unless(Invalid < Type(n) && Type(n) < HowMany); 65 | 66 | value = Type(n); 67 | } 68 | 69 | return true; 70 | } 71 | 72 | ENUM_METHOD(Size) 73 | chunkSize () const 74 | { 75 | return sizeof(Unsigned); 76 | } 77 | 78 | ENUM_METHOD(void) 79 | storeChunk (Byte*& bytes) const 80 | { 81 | Unsigned val = value; 82 | store(val, bytes); 83 | } 84 | 85 | ENUM_METHOD(void) 86 | fetchChunk (const Byte*& bytes) 87 | { 88 | Unsigned val; 89 | fetch(val, bytes); 90 | value = Type(val); 91 | } 92 | 93 | ENUM_METHOD(bool) 94 | operator == (const Enum& rhs) const 95 | { 96 | return value == rhs.value; 97 | } 98 | 99 | ENUM_METHOD(bool) 100 | operator != (const Enum& rhs) const 101 | { 102 | return value != rhs.value; 103 | } 104 | 105 | ENUM_METHOD(bool) 106 | operator == (const Type& otherValue) const 107 | { 108 | return value == otherValue; 109 | } 110 | 111 | ENUM_METHOD(bool) 112 | operator != (const Type& otherValue) const 113 | { 114 | return value != otherValue; 115 | } 116 | 117 | # undef ENUM_METHOD 118 | 119 | //------------------------------------------------------------------------------ 120 | 121 | template < typename Type, Type Invalid, Type HowMany > 122 | inline bool 123 | operator == (const Type& value, const Enum& that) 124 | { 125 | return that == value; 126 | } 127 | 128 | template < typename Type, Type Invalid, Type HowMany > 129 | inline bool 130 | operator != (const Type& value, const Enum& that) 131 | { 132 | return that != value; 133 | } 134 | 135 | //------------------------------------------------------------------------------ 136 | 137 | } 138 | -------------------------------------------------------------------------------- /headers/core/logging.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./types.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | enum Verbosity { 14 | 15 | InvalidVerbosity = -1, 16 | 17 | Debug, 18 | Info, 19 | Warning, 20 | Error, 21 | 22 | NumVerbosities 23 | }; 24 | 25 | # define UPLINK_LOG_PREFIX "UPLINK: " 26 | 27 | // Thread-safe catch-all. 28 | void log_line (Verbosity verbosity, CString message); 29 | 30 | inline CString log_prefix (Verbosity verbosity) 31 | { 32 | assert(int(InvalidVerbosity) < int(verbosity) && int(verbosity) < int(NumVerbosities)); 33 | 34 | static const CString prefixes [NumVerbosities] = 35 | { 36 | UPLINK_LOG_PREFIX "DEBUG : ", 37 | UPLINK_LOG_PREFIX "INFO : ", 38 | UPLINK_LOG_PREFIX "WARNING : ", 39 | UPLINK_LOG_PREFIX "ERROR : ", 40 | }; 41 | 42 | return prefixes[verbosity]; 43 | } 44 | 45 | inline void log_debug (CString message) { log_line(Debug , message); } 46 | inline void log_info (CString message) { log_line(Info , message); } 47 | inline void log_warning (CString message) { log_line(Warning, message); } 48 | inline void log_error (CString message) { log_line(Error , message); } 49 | 50 | # if UPLINK_DEBUG 51 | # define uplink_log_debug(...) ::uplink::log_debug( ::uplink::formatted(__VA_ARGS__).get()) 52 | #else 53 | # define uplink_log_debug(...) 54 | # endif 55 | # define uplink_log_info(...) ::uplink::log_info( ::uplink::formatted(__VA_ARGS__).get()) 56 | # define uplink_log_warning(...) ::uplink::log_warning(::uplink::formatted(__VA_ARGS__).get()) 57 | # define uplink_log_error(...) ::uplink::log_error( ::uplink::formatted(__VA_ARGS__).get()) 58 | 59 | //------------------------------------------------------------------------------ 60 | 61 | } // uplink namespace 62 | -------------------------------------------------------------------------------- /headers/core/macros.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | // Ubiquitous, code-shortening platform-independent preprocessor macros. 6 | 7 | # pragma once 8 | 9 | //------------------------------------------------------------------------------ 10 | 11 | # define header_only void __dummy_symbol__##__COUNTER__ () {} 12 | 13 | # define zero_delete(Ptr) delete (Ptr); (Ptr) = 0; 14 | 15 | # define sizeof_array(Array) sizeof(Array) / sizeof(Array[0]) 16 | 17 | # define non_copyable(Class) \ 18 | private: \ 19 | Class (const Class& copy); \ 20 | Class& operator = (const Class& rhs); 21 | 22 | # define unimplemented assert(false) 23 | 24 | // FIXME: Generate all the combinations, eventually. 25 | 26 | # define break_if(...) if ( (__VA_ARGS__)) break; 27 | # define break_unless(...) if (!(__VA_ARGS__)) break; 28 | 29 | # define continue_if(...) if ( (__VA_ARGS__)) continue; 30 | # define continue_unless(...) if (!(__VA_ARGS__)) continue; 31 | 32 | # define return_if(...) if ( (__VA_ARGS__)) { return; } 33 | # define return_unless(...) if (!(__VA_ARGS__)) { return; } 34 | 35 | # define return_true_if(...) if ( (__VA_ARGS__)) { return true; } 36 | # define return_true_unless(...) if (!(__VA_ARGS__)) { return true; } 37 | 38 | # define return_false_if(...) if ( (__VA_ARGS__)) { return false; } 39 | # define return_false_unless(...) if (!(__VA_ARGS__)) { return false; } 40 | 41 | # define return_zero_if(...) if ( (__VA_ARGS__)) { return 0; } 42 | # define return_zero_unless(...) if (!(__VA_ARGS__)) { return 0; } 43 | 44 | # define return_if_zero(...) if (0 == (__VA_ARGS__)) { return; } 45 | # define return_if_non_zero(...) if (0 != (__VA_ARGS__)) { return; } 46 | 47 | # define return_true_if_zero(...) if (0 == (__VA_ARGS__)) { return true; } 48 | # define return_true_if_non_zero(...) if (0 != (__VA_ARGS__)) { return true; } 49 | 50 | # define return_false_if_zero(...) if (0 == (__VA_ARGS__)) { return false; } 51 | # define return_false_if_non_zero(...) if (0 != (__VA_ARGS__)) { return false; } 52 | 53 | # define return_zero_if_zero(...) if (0 == (__VA_ARGS__)) { return 0; } 54 | # define return_zero_if_non_zero(...) if (0 != (__VA_ARGS__)) { return 0; } 55 | 56 | # define report_continue_if(What, ...) if ( (__VA_ARGS__)) { uplink_log_error(What); continue; } 57 | # define report_continue_unless(What, ...) if (!(__VA_ARGS__)) { uplink_log_error(What); continue; } 58 | 59 | # define report_if(What, ...) if ((__VA_ARGS__)) { uplink_log_error(What); return; } 60 | # define report_false_if(What, ...) if ((__VA_ARGS__)) { uplink_log_error(What); return false; } 61 | # define report_zero_if(What, ...) if ((__VA_ARGS__)) { uplink_log_error(What); return 0; } 62 | 63 | # define report_unless(What, ...) if (!(__VA_ARGS__)) { uplink_log_error(What); return; } 64 | # define report_false_unless(What, ...) if (!(__VA_ARGS__)) { uplink_log_error(What); return false; } 65 | # define report_zero_unless(What, ...) if (!(__VA_ARGS__)) { uplink_log_error(What); return 0; } 66 | 67 | # define report_if_zero(What, ...) if (0 == (__VA_ARGS__)) { uplink_log_error(What); return; } 68 | # define report_if_non_zero(What, ...) if (0 != (__VA_ARGS__)) { uplink_log_error(What); return; } 69 | 70 | # define report_false_if_zero(What, ...) if (0 == (__VA_ARGS__)) { uplink_log_error(What); return false; } 71 | # define report_false_if_non_zero(What, ...) if (0 != (__VA_ARGS__)) { uplink_log_error(What); return false; } 72 | 73 | # define report_zero_if_zero(What, ...) if (0 == (__VA_ARGS__)) { uplink_log_error(What); return 0; } 74 | # define report_zero_if_non_zero(What, ...) if (0 != (__VA_ARGS__)) { uplink_log_error(What); return 0; } 75 | 76 | //------------------------------------------------------------------------------ 77 | -------------------------------------------------------------------------------- /headers/core/memory.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include 8 | # include 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | class MemoryBlock 15 | { 16 | public: // Offer external access to the current allocation and deallocation routines, so that when we change our minds about these later on, we won't need to update dependent code. 17 | static uint8_t* allocate (size_t size) { return (uint8_t*) std::malloc(size); } 18 | static uint8_t* reallocate (uint8_t* data, size_t size) { return (uint8_t*) std::realloc(data, size); } 19 | static void deallocate (uint8_t* data) { std::free(data); } 20 | 21 | public: 22 | 23 | // Public direct access to the data 24 | uint8_t * Data; 25 | size_t Size; 26 | size_t AllocatedSize; // total allocated size for Data. May be bigger than Size. 27 | 28 | private: 29 | 30 | bool _freeWhenDone; 31 | 32 | typedef std::function ReleaseFunction; 33 | 34 | ReleaseFunction _releaseFunction; 35 | 36 | inline void callReleaseFunction() 37 | { 38 | if (_releaseFunction) { 39 | _releaseFunction(); // Call the release function, if specified. 40 | _releaseFunction = nullptr; 41 | } 42 | } 43 | 44 | void freeMemory(); 45 | 46 | public: 47 | 48 | // Destructor 49 | ~MemoryBlock(); 50 | 51 | // Default constructor 52 | MemoryBlock(); 53 | 54 | // Construct with already-existing data, and optionally take ownership and free when done. 55 | // We use a template for the function type to be able to catch ObjectiveC blocks and disable 56 | // them. Otherwise calling with a C++ lambda would be ambiguous. 57 | template 58 | MemoryBlock(uint8_t* data, size_t size, bool freeWhenDone, FunctionParameterType releaseFunction) 59 | : _freeWhenDone(freeWhenDone), Size(size), AllocatedSize(size), Data(data), _releaseFunction(releaseFunction) 60 | {} 61 | 62 | // Important! Here we delete the default copy constructor. This ensures 63 | // that we don't accidentally end up with dual-ownership over the same 64 | // underlying memory. 65 | MemoryBlock(const MemoryBlock& other) = delete; 66 | 67 | void clear (); 68 | 69 | void swapWith (MemoryBlock& other); 70 | void copyTo (MemoryBlock& other) const; 71 | 72 | /// Transfers ownership of data to the caller. (Data & Size fields remain populated, however.) 73 | void relinquishOwnership(); 74 | 75 | /// Transfers ownership of data to the caller, similarly to relinquishOwnership, but honoring the release function. 76 | void transferOwnership (ReleaseFunction& releaseFunction); 77 | 78 | // Construct with already-existing data, and optionally take ownership and free when done. 79 | // We use a template for the function type to be able to catch ObjectiveC blocks and disable 80 | // them. Otherwise calling with a C++ lambda would be ambiguous. 81 | /* 82 | Example usage: 83 | 84 | CFRetain(someCoreFoundationObjectRef); 85 | 86 | memoryBlock.ReplaceWith(dataPtr, dataLength, false , [someCoreFoundationObjectRef](){ 87 | CFRelease(someCoreFoundationObjectRef); 88 | }); 89 | */ 90 | template 91 | void ReplaceWith(uint8_t* data, size_t size, bool freeWhenDone, const FunctionParameterType& releaseFunction) 92 | { 93 | freeMemory(); 94 | 95 | this->Data = data; 96 | this->Size = size; 97 | this->AllocatedSize = size; // FIXME: this may not be true, it may be bigger, we could take an additional parameter. 98 | this->_freeWhenDone = freeWhenDone; 99 | _releaseFunction = releaseFunction; 100 | } 101 | 102 | // Resize the memory block as efficiently as possible. 103 | void Resize(size_t size, bool preserveData = false, bool reallocIfShrinking = false); 104 | 105 | #if __OBJC__ 106 | // For now, we don't allow Objective C blocks, since in that case we would need to call Block_copy. 107 | // Use a C++11 lambda instead. Thus the following overloads are disabled for safety. 108 | // FIXME: we could actually implement these if we wanted to. 109 | MemoryBlock(uint8_t* data, size_t size, bool freeWhenDone, void(^releaseFunction)(void)) = delete; 110 | void ReplaceWith(uint8_t* data, size_t size, bool freeWhenDone, void(^releaseFunction)(void)) = delete; 111 | #endif 112 | 113 | public: // Convenience methods. 114 | uint8_t* begin() { assert(0 != Data); return Data; } 115 | uint8_t* end () { assert(0 != Data && 0 < Size); return Data + Size; } 116 | }; 117 | 118 | //------------------------------------------------------------------------------ 119 | 120 | } 121 | 122 | # include "./memory.hpp" 123 | -------------------------------------------------------------------------------- /headers/core/memory.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./memory.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | inline 14 | MemoryBlock::MemoryBlock() : 15 | _freeWhenDone(false), Size(0), AllocatedSize(0), Data(nullptr), _releaseFunction(nullptr) 16 | { 17 | } 18 | 19 | inline 20 | MemoryBlock::~MemoryBlock() 21 | { 22 | this->freeMemory(); 23 | } 24 | 25 | inline void 26 | MemoryBlock::freeMemory() 27 | { 28 | if(_freeWhenDone) 29 | deallocate((uint8_t*)this->Data); // Free memory, if requested to. 30 | 31 | callReleaseFunction(); 32 | } 33 | 34 | inline void 35 | MemoryBlock::swapWith (MemoryBlock& other) 36 | { 37 | std::swap (Data, other.Data); 38 | std::swap (Size, other.Size); 39 | std::swap (AllocatedSize, other.AllocatedSize); 40 | std::swap (_freeWhenDone, other._freeWhenDone); 41 | std::swap (_releaseFunction, other._releaseFunction); 42 | } 43 | 44 | inline void 45 | MemoryBlock::copyTo (MemoryBlock& other) const 46 | { 47 | other.Resize(Size); 48 | 49 | if (Size > 0) 50 | memcpy (other.Data, Data, Size); 51 | } 52 | 53 | inline void 54 | MemoryBlock::clear () 55 | { 56 | freeMemory(); 57 | 58 | Data = nullptr; 59 | Size = 0; 60 | AllocatedSize = 0; 61 | _freeWhenDone = false; 62 | _releaseFunction = nullptr; 63 | } 64 | 65 | inline void 66 | MemoryBlock::Resize(size_t newSize, bool preserveData, bool reclaimExtraIfShrinking) 67 | { 68 | // Size is right already: 69 | if(Size == newSize) return; 70 | 71 | // Need to shrink, but don't need to reclaim, so set size & return: 72 | if(AllocatedSize >= newSize && !reclaimExtraIfShrinking) 73 | { 74 | Size = newSize; 75 | return; 76 | } 77 | 78 | // Below here, we need to actually allocate/reallocate memory: 79 | 80 | // Empty? We can jump directly to malloc. 81 | if(Data == NULL && AllocatedSize == 0) 82 | { 83 | freeMemory(); 84 | 85 | Data = allocate(newSize); 86 | AllocatedSize = newSize; 87 | Size = newSize; 88 | _freeWhenDone = true; 89 | } 90 | 91 | bool canFreeMemory = _freeWhenDone || _releaseFunction; 92 | 93 | if (!canFreeMemory) 94 | assert(false); // MemoryBlock needs to resize, but cannot free its current memory. Very likely a leak! 95 | 96 | if (_freeWhenDone) 97 | { 98 | // Use realloc if we're asked to preserve. Otherwise, free+malloc. 99 | if(preserveData) 100 | { 101 | Data = reallocate(Data, newSize); 102 | Size = newSize; 103 | AllocatedSize = newSize; 104 | } 105 | else 106 | { 107 | deallocate(Data); 108 | 109 | // Allocate a new buffer. 110 | // Note that _freeWhenDone must remain true to manage this new memory. 111 | Data = allocate(newSize); 112 | Size = newSize; 113 | AllocatedSize = newSize; 114 | } 115 | } 116 | 117 | if (_releaseFunction) 118 | { 119 | assert(_freeWhenDone == false); // MemoryBlock cannot have both freeWhenDone and a release block. 120 | 121 | uint8_t * previousData = Data; 122 | size_t previousSize = Size; 123 | 124 | // If we don't need to preserve contents, release earlier (less max memory usage) 125 | if(!preserveData) 126 | callReleaseFunction(); 127 | 128 | // Allocate a new buffer. 129 | Data = allocate(newSize); 130 | Size = newSize; 131 | AllocatedSize = newSize; 132 | _freeWhenDone = true; // We now must manage this buffer. 133 | 134 | if(preserveData) { 135 | memcpy(Data, previousData, previousSize); 136 | callReleaseFunction(); 137 | } 138 | 139 | } 140 | } 141 | 142 | inline void 143 | MemoryBlock::relinquishOwnership() 144 | { 145 | assert(!_releaseFunction); // Extract with a release function is not supported yet. 146 | _freeWhenDone = false; // Caller will now be responsible for this memory 147 | } 148 | 149 | inline void 150 | MemoryBlock::transferOwnership(ReleaseFunction& releaseFunction) 151 | { 152 | if (_releaseFunction) 153 | { 154 | releaseFunction = _releaseFunction; // transfer the release function. 155 | } 156 | else 157 | { 158 | uint8_t* data = Data; 159 | releaseFunction = [data]() { deallocate(data); }; 160 | } 161 | 162 | _releaseFunction = ReleaseFunction(); 163 | 164 | _freeWhenDone = false; // Caller will now be responsible for this memory 165 | } 166 | 167 | //------------------------------------------------------------------------------ 168 | 169 | } 170 | -------------------------------------------------------------------------------- /headers/core/platform.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | #pragma once 6 | 7 | #include "platform.h" 8 | 9 | namespace uplink { 10 | 11 | inline 12 | TCPConnection::TCPConnection () 13 | : disconnecting(false) 14 | { 15 | } 16 | 17 | inline 18 | TCPConnection::~TCPConnection () 19 | { 20 | } 21 | 22 | inline TCPConnection* 23 | TCPConnection::connect (CString host, uint16 port) 24 | { 25 | ScopedProfiledTask _(ProfilerTask_TCPConnection); 26 | 27 | return TCPConnection_connect(host, port); 28 | } 29 | 30 | inline TCPConnection* 31 | TCPConnection::create (int descriptor) 32 | { 33 | return TCPConnection_create(descriptor); 34 | } 35 | 36 | } // uplink namespace 37 | -------------------------------------------------------------------------------- /headers/core/platforms/core/apple-image-codecs.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | namespace uplink { 8 | 9 | //------------------------------------------------------------------------------ 10 | 11 | class MemoryBlock; 12 | 13 | float CoreGraphicsJpegQualityFromNormalizedLibJpegQuality(float normalizedLibJpegQuality); 14 | 15 | bool 16 | encode_image ( 17 | graphics_ImageCodec imageCodec, 18 | const uint8_t* inputBuffer, 19 | size_t inputSize, 20 | graphics_PixelFormat inputFormat, 21 | size_t inputWidth, 22 | size_t inputHeight, 23 | MemoryBlock& outputMemoryBlock, 24 | float outputQuality 25 | ); 26 | 27 | bool 28 | decode_image ( 29 | 30 | graphics_ImageCodec imageCodec, 31 | const uint8_t* inputBuffer, 32 | size_t inputSize, 33 | graphics_PixelFormat outputFormat, 34 | size_t& outputWidth, 35 | size_t& outputHeight, 36 | MemoryBlock& outputMemoryBlock 37 | ); 38 | 39 | //------------------------------------------------------------------------------ 40 | 41 | } 42 | -------------------------------------------------------------------------------- /headers/core/platforms/core/apple.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./posix.h" 8 | # include "./apple-image-codecs.h" 9 | 10 | # define UPLINK_HAS_APPLE 1 11 | 12 | # if defined(__OBJC__) 13 | # include "./objc.h" 14 | # endif 15 | 16 | namespace uplink { 17 | 18 | //------------------------------------------------------------------------------ 19 | 20 | int64 getTickCount (); 21 | double getTickFrequency (); 22 | 23 | //------------------------------------------------------------------------------ 24 | 25 | } 26 | -------------------------------------------------------------------------------- /headers/core/platforms/core/apple.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./apple.h" 8 | # include 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | inline int64 15 | getTickCount () 16 | { 17 | return int64(mach_absolute_time()); 18 | } 19 | 20 | inline double 21 | getTickFrequency () 22 | { 23 | static double frequency = 0; 24 | 25 | if (frequency != 0) 26 | return frequency; 27 | 28 | mach_timebase_info_data_t info; 29 | mach_timebase_info(&info); 30 | 31 | frequency = info.denom * 1e9 / info.numer; 32 | 33 | return frequency; 34 | } 35 | 36 | inline void 37 | platform_startup () 38 | { 39 | // Nothing to do. 40 | } 41 | 42 | inline void 43 | platform_shutdown () 44 | { 45 | // Nothing to do. 46 | } 47 | 48 | //------------------------------------------------------------------------------ 49 | 50 | } 51 | 52 | # include "./posix.hpp" 53 | 54 | # if UPLINK_HAS_OBJC 55 | # include "./objc.hpp" 56 | # endif 57 | 58 | # include "./apple-image-codecs.hpp" 59 | -------------------------------------------------------------------------------- /headers/core/platforms/core/bsd-sockets.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include 8 | # include 9 | # include 10 | 11 | # define UPLINK_HAS_BSD_SOCKETS 1 12 | 13 | namespace uplink { 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | struct BSDSocket 18 | { 19 | bool enableOption (int option); 20 | bool setTimeOption (int option, int sec, int usec); 21 | 22 | int fd; 23 | sockaddr_in addr; 24 | }; 25 | 26 | //------------------------------------------------------------------------------ 27 | 28 | class BSDTCPConnection : public TCPConnection 29 | { 30 | public: 31 | BSDTCPConnection (int descriptor); 32 | 33 | public: 34 | virtual ~BSDTCPConnection (); 35 | 36 | public: 37 | virtual bool read ( Byte* bytes, Size size); 38 | virtual bool write (const Byte* bytes, Size size); 39 | 40 | private: 41 | BSDSocket socket; 42 | }; 43 | 44 | //------------------------------------------------------------------------------ 45 | 46 | struct BSDUDPBroadcaster : UDPBroadcaster 47 | { 48 | static UDPBroadcaster* create (int port); 49 | 50 | bool broadcast (const Byte* bytes, Size length); 51 | 52 | BSDSocket socket; 53 | }; 54 | 55 | //------------------------------------------------------------------------------ 56 | 57 | struct BSDUDPListener : UDPListener 58 | { 59 | static UDPListener* create (int port); 60 | 61 | bool receive (Byte* bytes, Size size, NetworkAddress& sender); 62 | 63 | BSDSocket socket; 64 | }; 65 | 66 | //------------------------------------------------------------------------------ 67 | 68 | } 69 | -------------------------------------------------------------------------------- /headers/core/platforms/core/objc.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | // Objective-C helpers. 6 | 7 | # pragma once 8 | 9 | # include "../../types.h" 10 | 11 | # define UPLINK_HAS_OBJC 1 12 | 13 | # include 14 | # include 15 | # include 16 | 17 | # define OBJC_CLASS(Name) @class Name 18 | # define OBJC_CLASS(Name) typedef struct objc_object Name 19 | 20 | namespace uplink { 21 | 22 | //------------------------------------------------------------------------------ 23 | 24 | NSString* toNSString (const String& str); 25 | String fromNSString (NSString* str); 26 | 27 | //------------------------------------------------------------------------------ 28 | 29 | } 30 | -------------------------------------------------------------------------------- /headers/core/platforms/core/objc.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | // Objective-C helpers. 6 | 7 | # pragma once 8 | 9 | # include "./objc.h" 10 | 11 | namespace uplink { 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | inline NSString* 16 | toNSString (const String& str) 17 | { 18 | return [ NSString stringWithUTF8String: str.c_str() ]; 19 | } 20 | 21 | inline String 22 | fromNSString (NSString* str) 23 | { 24 | return [ str UTF8String ]; 25 | } 26 | 27 | inline void 28 | console_log_line (Verbosity verbosity, CString message) 29 | { 30 | NSLog(@"%s%s\n", log_prefix(verbosity), message); 31 | } 32 | 33 | //------------------------------------------------------------------------------ 34 | 35 | } 36 | -------------------------------------------------------------------------------- /headers/core/platforms/core/posix.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./pthreads.h" 8 | # include "./bsd-sockets.h" 9 | 10 | # define UPLINK_HAS_POSIX 1 11 | 12 | namespace uplink { 13 | 14 | //------------------------------------------------------------------------------ 15 | 16 | int vasprintf (char** output, const char* format, va_list args); 17 | 18 | String getLocalHostName (); 19 | 20 | int64 getTickCount (); 21 | 22 | double getTickFrequency (); 23 | 24 | //------------------------------------------------------------------------------ 25 | 26 | } 27 | -------------------------------------------------------------------------------- /headers/core/platforms/core/posix.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./posix.h" 8 | # include "../../macros.h" 9 | # include 10 | # include 11 | # include 12 | # include 13 | # include 14 | # include 15 | 16 | namespace uplink { 17 | 18 | //------------------------------------------------------------------------------ 19 | 20 | inline int 21 | vasprintf (char** output, const char* format, va_list args) 22 | { 23 | return ::vasprintf(output, format, args); 24 | } 25 | 26 | # if !UPLINK_HAS_OBJC 27 | inline void 28 | console_log_line (Verbosity verbosity, CString message) 29 | { 30 | printf("%s%s\n", log_prefix(verbosity), message); 31 | } 32 | # endif 33 | 34 | inline String 35 | getLocalHostName () 36 | { 37 | char name [256]; 38 | 39 | if (0 != gethostname(name, 255)) 40 | return "localhost"; 41 | 42 | name[255] = '\0'; 43 | 44 | return name; 45 | } 46 | 47 | # if !UPLINK_HAS_APPLE 48 | inline int64 49 | getTickCount () 50 | { 51 | struct timespec t; 52 | 53 | clock_gettime(CLOCK_MONOTONIC, &t); 54 | 55 | return int64(t.tv_sec * 1000000000 + t.tv_nsec); 56 | } 57 | 58 | inline double 59 | getTickFrequency () 60 | { 61 | return 1e9; 62 | } 63 | #endif 64 | 65 | //------------------------------------------------------------------------------ 66 | 67 | } 68 | 69 | # include "./bsd-sockets.hpp" 70 | # include "./pthreads.hpp" 71 | -------------------------------------------------------------------------------- /headers/core/platforms/core/pthreads.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include 8 | 9 | # define UPLINK_THREAD pthread_t 10 | # define UPLINK_MUTEX pthread_mutex_t 11 | # define UPLINK_CONDITION pthread_cond_t 12 | -------------------------------------------------------------------------------- /headers/core/platforms/core/pthreads.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # include 6 | # include 7 | 8 | namespace uplink { namespace platform { 9 | 10 | //------------------------------------------------------------------------------ 11 | 12 | inline bool IsCurrentThread (const Thread& thread) 13 | { 14 | return pthread_equal(pthread_self(), thread); 15 | } 16 | 17 | //------------------------------------------------------------------------------ 18 | 19 | inline Condition* ConditionCreate() 20 | { 21 | Condition* condition = (Condition*)malloc(sizeof(Condition)); 22 | pthread_cond_init(condition, NULL); 23 | return condition; 24 | } 25 | 26 | inline void ConditionWait(Condition* condition, Mutex* mutex) 27 | { 28 | pthread_cond_wait(condition, mutex); 29 | } 30 | 31 | inline void ConditionSignal(Condition* condition) 32 | { 33 | pthread_cond_signal(condition); 34 | } 35 | 36 | inline void ConditionBroadcast (Condition* condition) 37 | { 38 | pthread_cond_broadcast(condition); 39 | } 40 | 41 | inline void ConditionDestroy(Condition* condition) 42 | { 43 | pthread_cond_destroy(condition); 44 | } 45 | 46 | //------------------------------------------------------------------------------ 47 | 48 | inline void ThreadSetPriority(Thread * thread, ThreadPriority priority) 49 | { 50 | sched_param schedParam; 51 | int kPolicy = -1; 52 | pthread_getschedparam(*thread, &kPolicy, &schedParam); 53 | 54 | int priority_to_set; 55 | 56 | switch (priority) { 57 | case ThreadPriorityLow: 58 | priority_to_set = sched_get_priority_min( kPolicy ); 59 | break; 60 | case ThreadPriorityNormal: 61 | return; 62 | case ThreadPriorityHigh: 63 | priority_to_set = sched_get_priority_max( kPolicy ); 64 | break; 65 | default: 66 | return; 67 | } 68 | 69 | schedParam.sched_priority = priority_to_set; 70 | pthread_setschedparam(*thread, kPolicy, &schedParam); 71 | } 72 | 73 | inline void ThreadStart(Thread * thread, void *(*func)(void *), void * state) 74 | { 75 | // Create the thread using POSIX routines. 76 | pthread_attr_t attr; 77 | int returnVal; 78 | 79 | returnVal = pthread_attr_init(&attr); 80 | 81 | //assert(!returnVal); 82 | 83 | returnVal = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 84 | 85 | /* 86 | //Priority Setting. 87 | const int kPolicy = SCHED_RR; 88 | int minPriority = sched_get_priority_min( kPolicy ); 89 | 90 | sched_param schedParam; 91 | schedParam.sched_priority = minPriority; 92 | pthread_attr_setschedparam( &attr, &schedParam ); 93 | pthread_attr_setschedpolicy( &attr, kPolicy ); 94 | */ 95 | 96 | //assert(!returnVal); 97 | 98 | int threadError = pthread_create(thread, &attr, func, state); 99 | 100 | returnVal = pthread_attr_destroy(&attr); 101 | 102 | if (threadError != 0) { 103 | // Report an error. 104 | } 105 | } 106 | 107 | inline void ThreadSleep(float seconds) { 108 | usleep( (int)(1e6 * seconds) ); 109 | } 110 | 111 | //------------------------------------------------------------------------------ 112 | 113 | inline Mutex* CreateMutexObject() { 114 | Mutex* mutex = (Mutex*)malloc(sizeof(Mutex)); 115 | pthread_mutex_init(mutex, NULL); 116 | return mutex; 117 | } 118 | 119 | inline void DestroyMutexObject(Mutex* mutex) { 120 | pthread_mutex_destroy(mutex); 121 | } 122 | 123 | inline bool MutexTryLock(Mutex* mutex) { return (pthread_mutex_trylock(mutex) == 0); } 124 | inline void MutexLock(Mutex* mutex) { pthread_mutex_lock(mutex); } 125 | inline void MutexUnlock(Mutex* mutex) { pthread_mutex_unlock(mutex); } 126 | 127 | //------------------------------------------------------------------------------ 128 | 129 | } } 130 | -------------------------------------------------------------------------------- /headers/core/platforms/core/win32-api.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | #pragma once 6 | 7 | // This monstrosity exists because the sequence of inclusion of windows main and socket headers actually matters. 8 | 9 | # ifndef _WINDOWS_ // Then no other header already included Windows.h, yet. 10 | # define NOMINMAX 11 | # define VC_EXTRALEAN 12 | # define WIN32_LEAN_AND_MEAN 13 | # include 14 | # include 15 | # include 16 | # pragma comment(lib, "ws2_32.lib") 17 | # else // We're in trouble, because WinSock2.h cannot be included from here. 18 | # ifndef _WINSOCK2API_ 19 | # error "The Windows.h header has already been included without WinSock2 support. You must include WinSock2.h before it. See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms738562.aspx." 20 | # endif 21 | # endif 22 | -------------------------------------------------------------------------------- /headers/core/platforms/core/windows-image-codecs.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | class MemoryBlock; 15 | 16 | bool 17 | encode_image ( 18 | graphics_ImageCodec imageCodec, 19 | const uint8_t* inputBuffer, 20 | size_t inputSize, 21 | graphics_PixelFormat inputFormat, 22 | size_t inputWidth, 23 | size_t inputHeight, 24 | MemoryBlock& outputMemoryBlock, 25 | float outputQuality 26 | ); 27 | 28 | bool 29 | decode_image ( 30 | graphics_ImageCodec imageCodec, 31 | const uint8_t* inputBuffer, 32 | size_t inputSize, 33 | graphics_PixelFormat outputFormat, 34 | size_t& outputWidth, 35 | size_t& outputHeight, 36 | MemoryBlock& outputMemoryBlock 37 | ); 38 | 39 | //------------------------------------------------------------------------------ 40 | 41 | } // uplink namespace 42 | -------------------------------------------------------------------------------- /headers/core/platforms/core/windows-sockets.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./win32-api.h" 8 | 9 | # define UPLINK_HAS_WINDOWS_SOCKETS 1 10 | 11 | namespace uplink { 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | struct WindowsSocket 16 | { 17 | WindowsSocket () 18 | { 19 | 20 | } 21 | 22 | struct DLL 23 | { 24 | DLL () 25 | { 26 | version = MAKEWORD(2, 2); 27 | 28 | report_unless("Windows socket DLL failed to load.", 0 == WSAStartup(version, &data)); 29 | } 30 | 31 | ~DLL () 32 | { 33 | WSACleanup(); 34 | } 35 | 36 | static void require () 37 | { 38 | static const DLL dll; 39 | } 40 | 41 | WORD version; 42 | WSADATA data; 43 | }; 44 | 45 | bool enableOption (int option); 46 | bool setTimeOption (int option, int msec); 47 | 48 | SOCKET fd; 49 | sockaddr_in addr; 50 | }; 51 | 52 | //------------------------------------------------------------------------------ 53 | 54 | class WindowsTCPConnection : public TCPConnection 55 | { 56 | public: 57 | WindowsTCPConnection (int descriptor); 58 | 59 | public: 60 | virtual ~WindowsTCPConnection (); 61 | 62 | public: 63 | virtual bool read ( Byte* bytes, Size size); 64 | virtual bool write (const Byte* bytes, Size size); 65 | 66 | private: 67 | WindowsSocket socket; 68 | }; 69 | 70 | //------------------------------------------------------------------------------ 71 | 72 | struct WindowsUDPBroadcaster : UDPBroadcaster 73 | { 74 | virtual bool broadcast (const Byte* bytes, Size length); 75 | 76 | WindowsSocket socket; 77 | }; 78 | 79 | //------------------------------------------------------------------------------ 80 | 81 | struct WindowsUDPListener : UDPListener 82 | { 83 | static UDPListener* create (int port); 84 | 85 | virtual bool receive (Byte* bytes, Size size, NetworkAddress& sender); 86 | 87 | WindowsSocket socket; 88 | }; 89 | 90 | //------------------------------------------------------------------------------ 91 | 92 | } 93 | -------------------------------------------------------------------------------- /headers/core/platforms/core/windows-threads.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./win32-api.h" 8 | 9 | # define UPLINK_THREAD HANDLE 10 | # define UPLINK_MUTEX CRITICAL_SECTION 11 | # define UPLINK_CONDITION CONDITION_VARIABLE 12 | -------------------------------------------------------------------------------- /headers/core/platforms/core/windows-threads.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | #include "windows-threads.h" 6 | 7 | namespace uplink { namespace platform { 8 | 9 | //------------------------------------------------------------------------------ 10 | 11 | inline bool 12 | IsCurrentThread (const Thread& thread) 13 | { 14 | return GetCurrentThread() == thread; 15 | } 16 | 17 | //------------------------------------------------------------------------------ 18 | 19 | inline Condition* 20 | ConditionCreate() 21 | { 22 | Condition* condition = new Condition; 23 | 24 | InitializeConditionVariable(condition); 25 | 26 | return condition; 27 | } 28 | 29 | inline void 30 | ConditionWait (Condition* condition, Mutex* mutex) 31 | { 32 | SleepConditionVariableCS(condition, mutex, INFINITE); 33 | } 34 | 35 | inline void 36 | ConditionSignal (Condition* condition) 37 | { 38 | WakeConditionVariable(condition); 39 | } 40 | 41 | inline void 42 | ConditionBroadcast (Condition* condition) 43 | { 44 | WakeAllConditionVariable(condition); 45 | } 46 | 47 | inline void 48 | ConditionDestroy(Condition* condition) 49 | { 50 | delete condition; 51 | } 52 | 53 | //------------------------------------------------------------------------------ 54 | 55 | typedef void* (*ThreadFunction)(void*); 56 | 57 | struct ThreadState 58 | { 59 | ThreadFunction func; 60 | void* state; 61 | }; 62 | 63 | inline DWORD WINAPI 64 | threadMain (LPVOID lpParam) 65 | { 66 | ThreadState* ts = reinterpret_cast(lpParam); 67 | 68 | void* ret = ts->func(ts->state); 69 | 70 | delete ts; 71 | 72 | return reinterpret_cast(ret); 73 | } 74 | 75 | //------------------------------------------------------------------------------ 76 | 77 | inline void 78 | ThreadSetPriority (Thread * thread, ThreadPriority priority) 79 | { 80 | assert(false); // FIXME: Implement. 81 | } 82 | 83 | inline void 84 | ThreadStart (Thread* thread, void* (*func) (void*), void* state) 85 | { 86 | ThreadState * ts = new ThreadState; 87 | ts->func = func; 88 | ts->state = state; 89 | 90 | DWORD tid; 91 | 92 | *thread = CreateThread ( 93 | 0, // Security attributes 94 | 0, // Stack size 95 | threadMain, 96 | ts, 97 | 0, // Could use CREATE_SUSPENDED here 98 | &tid 99 | ); 100 | } 101 | 102 | inline void 103 | ThreadSleep (float seconds) 104 | { 105 | Sleep((int)(seconds * 1000 + 0.5)); 106 | } 107 | 108 | //------------------------------------------------------------------------------ 109 | 110 | inline Mutex* 111 | CreateMutexObject() 112 | { 113 | Mutex* mutex = new Mutex; 114 | 115 | InitializeCriticalSection(mutex); 116 | 117 | return mutex; 118 | } 119 | 120 | inline void 121 | DestroyMutexObject(Mutex* mutex) 122 | { 123 | DeleteCriticalSection(mutex); 124 | 125 | delete mutex; 126 | } 127 | 128 | inline bool 129 | MutexTryLock(Mutex* mutex) 130 | { 131 | return FALSE != TryEnterCriticalSection(mutex); 132 | } 133 | 134 | inline void 135 | MutexLock (Mutex* mutex) 136 | { 137 | EnterCriticalSection(mutex); 138 | } 139 | 140 | inline void 141 | MutexUnlock (Mutex* mutex) 142 | { 143 | LeaveCriticalSection(mutex); 144 | } 145 | 146 | //------------------------------------------------------------------------------ 147 | 148 | } } 149 | -------------------------------------------------------------------------------- /headers/core/platforms/ios.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/apple.h" 8 | 9 | # define UPLINK_HAS_IOS 1 10 | 11 | # if TARGET_IPHONE_SIMULATOR 12 | # define UPLINK_HAS_IOS_SIMULATOR 1 13 | # else 14 | # define UPLINK_HAS_IOS_DEVICE 1 15 | # endif 16 | 17 | namespace uplink { 18 | 19 | //------------------------------------------------------------------------------ 20 | 21 | //------------------------------------------------------------------------------ 22 | 23 | } 24 | -------------------------------------------------------------------------------- /headers/core/platforms/ios.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./ios.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | } 16 | 17 | # include "./core/apple.hpp" 18 | -------------------------------------------------------------------------------- /headers/core/platforms/osx.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/apple.h" 8 | 9 | # define UPLINK_HAS_OSX 1 10 | 11 | namespace uplink { 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | } 18 | -------------------------------------------------------------------------------- /headers/core/platforms/osx.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./osx.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | } 16 | 17 | # include "./core/apple.hpp" 18 | -------------------------------------------------------------------------------- /headers/core/platforms/windows.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/win32-api.h" 8 | # include "./core/windows-sockets.h" 9 | # include "./core/windows-threads.h" 10 | # include "./core/windows-image-codecs.h" 11 | # include 12 | # include 13 | # include 14 | 15 | # define UPLINK_HAS_WINDOWS 1 16 | 17 | namespace uplink { 18 | 19 | //------------------------------------------------------------------------------ 20 | 21 | inline int 22 | vasprintf (char** output, const char* format, va_list args) 23 | { 24 | *output = 0; 25 | const int length = _vscprintf(format, args); 26 | 27 | if (length < 0) 28 | return 0; 29 | 30 | *output = reinterpret_cast(malloc(length + 1)); 31 | 32 | if (0 == *output) 33 | return 0; 34 | 35 | vsnprintf_s(*output, length + 1, length, format, args); 36 | 37 | // Output is null-terminated. 38 | 39 | return length; 40 | } 41 | 42 | inline void 43 | console_log_line (Verbosity verbosity, CString message) 44 | { 45 | CStringPtr line = formatted("%s%s\n", log_prefix(verbosity), message); 46 | 47 | OutputDebugString(line.get()); 48 | } 49 | 50 | inline String 51 | getLocalHostName () 52 | { 53 | char name [256]; 54 | 55 | if (0 != gethostname(name, 255)) 56 | return "localhost"; 57 | 58 | name[255] = '\0'; 59 | 60 | return name; 61 | } 62 | 63 | inline int64 64 | getTickCount () 65 | { 66 | LARGE_INTEGER counter; 67 | 68 | QueryPerformanceCounter(&counter); 69 | 70 | return int64(counter.QuadPart); 71 | } 72 | 73 | inline double 74 | getTickFrequency () 75 | { 76 | LARGE_INTEGER frequency; 77 | 78 | QueryPerformanceFrequency(&frequency); 79 | 80 | return double(frequency.QuadPart); 81 | } 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /headers/core/platforms/windows.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./windows.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | inline void 14 | platform_startup () 15 | { 16 | WindowsSocket::DLL::require(); 17 | } 18 | 19 | inline void 20 | platform_shutdown () 21 | { 22 | 23 | } 24 | 25 | //------------------------------------------------------------------------------ 26 | 27 | } 28 | 29 | # include "./core/windows-sockets.hpp" 30 | # include "./core/windows-threads.hpp" 31 | # include "./core/windows-image-codecs.hpp" 32 | -------------------------------------------------------------------------------- /headers/core/profiling.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./types.h" 8 | # include 9 | 10 | namespace uplink { 11 | 12 | #define UPLINK_PROFILER_TASKS() \ 13 | UPLINK_PROFILER_TASK(TCPConnection) \ 14 | UPLINK_PROFILER_TASK(ServicePublishing) \ 15 | UPLINK_PROFILER_TASK(ReadMessage) \ 16 | UPLINK_PROFILER_TASK(CompressImage) \ 17 | UPLINK_PROFILER_TASK(DecompressImage) \ 18 | UPLINK_PROFILER_TASK(SocketReadLoop) \ 19 | UPLINK_PROFILER_TASK(WriteMessage) \ 20 | UPLINK_PROFILER_TASK(SocketWriteLoop) \ 21 | UPLINK_PROFILER_TASK(EncodeImage) \ 22 | UPLINK_PROFILER_TASK(DecodeImage) 23 | 24 | enum ProfilerTask { 25 | ProfilerTask_Invalid = -1, 26 | 27 | # define UPLINK_PROFILER_TASK(Name) \ 28 | ProfilerTask_##Name, 29 | UPLINK_PROFILER_TASKS() 30 | # undef UPLINK_PROFILER_TASK 31 | 32 | ProfilerTask_HowMany 33 | }; 34 | 35 | void profiler_task_started (ProfilerTask task); 36 | void profiler_task_stopped (ProfilerTask task); 37 | 38 | struct ScopedProfiledTask 39 | { 40 | ScopedProfiledTask (ProfilerTask task) : task(task) 41 | { 42 | # if UPLINK_PROFILE 43 | profiler_task_started(task); 44 | #endif 45 | } 46 | ~ScopedProfiledTask () 47 | { 48 | # if UPLINK_PROFILE 49 | profiler_task_stopped(task); 50 | # endif 51 | } 52 | 53 | ProfilerTask task; 54 | }; 55 | 56 | struct Profiler 57 | { 58 | Profiler () 59 | { 60 | # if UPLINK_PROFILE 61 | taskIds.reserve(ProfilerTask_HowMany); 62 | # endif 63 | } 64 | 65 | virtual ~Profiler () {} 66 | 67 | virtual void registerTasks () 68 | { 69 | if (!UPLINK_PROFILE) 70 | return; 71 | 72 | # define UPLINK_PROFILER_TASK(Name) \ 73 | taskIds.push_back(registerTask(#Name, #Name)); 74 | UPLINK_PROFILER_TASKS() 75 | # undef UPLINK_PROFILER_TASK 76 | } 77 | 78 | virtual int registerTask (CString name, CString label) = 0; 79 | 80 | virtual void taskStarted (int identifier) = 0; 81 | virtual void taskStopped (int identifier) = 0; 82 | 83 | std::vector taskIds; 84 | }; 85 | 86 | } // uplink namespace 87 | -------------------------------------------------------------------------------- /headers/core/queues.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./threads.h" 8 | # include "./clocks.h" 9 | # include 10 | # include 11 | # include 12 | 13 | namespace uplink { 14 | 15 | template < class Item > 16 | class Queue 17 | { 18 | public: 19 | enum DroppingStrategy 20 | { 21 | OldestOneDroppingStrategy, 22 | RandomOneDroppingStrategy, 23 | RandomFivePercentDroppingStrategy, 24 | OneEveryTenDroppingStrategy 25 | }; 26 | 27 | public: 28 | Queue (); 29 | ~Queue (); 30 | 31 | public: 32 | void pushByCopy (const Item& newItem); 33 | void pushBySwap (Item& newItem); 34 | 35 | public: 36 | bool popBySwap (Item& lastItem); 37 | 38 | public: 39 | void isEmpty (); 40 | float getUsageRatio () const; 41 | 42 | public: 43 | void setMaximumSize (int newMaximumSize); 44 | void setDroppingStategy (DroppingStrategy newStrategy); 45 | 46 | public: 47 | void reset (); 48 | 49 | public: 50 | double currentPushingRate () const; 51 | double currentPoppingRate () const; 52 | 53 | private: 54 | template < class UpdateMethod > 55 | void push (Item& newItem); 56 | 57 | private: 58 | void dropRandomly (int howMany = 1); 59 | void drop (); 60 | 61 | private: 62 | typedef std::list Items; 63 | typedef typename Items::iterator ItemsIterator; 64 | 65 | private: 66 | mutable Mutex mutex; 67 | int count; // C++98 allows for o(n) std::list size implementations. 68 | Items items; 69 | 70 | private: 71 | int maximumSize; 72 | DroppingStrategy droppingStrategy; 73 | 74 | private: 75 | RateEstimator pushingRate; 76 | RateEstimator poppingRate; 77 | }; 78 | 79 | } 80 | 81 | # include "./queues.hpp" 82 | -------------------------------------------------------------------------------- /headers/core/shift2depth.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | #pragma once 6 | 7 | // FIXME: Dynamically compute the table with the camera info data, instead of using this fixed one. 8 | 9 | # include "./types.h" 10 | 11 | namespace uplink { 12 | 13 | uint16 shift2depth (uint16 shift); 14 | void shift2depth (uint16* buffer, size_t size); 15 | 16 | //------------------------------------------------------------------------------ 17 | 18 | } 19 | 20 | #include "shift2depth.hpp" 21 | -------------------------------------------------------------------------------- /headers/core/streams.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./types.h" 8 | # include "./bytes.h" 9 | # include 10 | # include 11 | 12 | namespace uplink { 13 | 14 | //------------------------------------------------------------------------------ 15 | 16 | class InputStream 17 | { 18 | public: 19 | enum { UnknownSize = Size(-1) }; 20 | 21 | public: 22 | virtual ~InputStream () {} 23 | 24 | public: 25 | virtual bool read (Byte* bytes, Size size) = 0; 26 | virtual Size available () const { return UnknownSize; } 27 | }; 28 | 29 | //------------------------------------------------------------------------------ 30 | 31 | class OutputStream 32 | { 33 | public: 34 | virtual ~OutputStream () {} 35 | 36 | public: 37 | virtual bool write (const Byte* bytes, Size size) = 0; 38 | }; 39 | 40 | //------------------------------------------------------------------------------ 41 | 42 | struct DuplexStream 43 | : InputStream 44 | , OutputStream 45 | { 46 | 47 | }; 48 | 49 | //------------------------------------------------------------------------------ 50 | 51 | struct Streamable 52 | { 53 | virtual bool readFrom (InputStream & input ) = 0; 54 | virtual bool writeTo (OutputStream& output) const = 0; 55 | }; 56 | 57 | //------------------------------------------------------------------------------ 58 | 59 | struct RawBufferInputStream : InputStream 60 | { 61 | RawBufferInputStream (Byte* input, Size length) 62 | : input(input) 63 | , length(length) 64 | , offset(0) 65 | , count(0) 66 | { 67 | 68 | } 69 | 70 | virtual bool read (Byte* bytes, Size size) 71 | { 72 | if (length < (offset + size)) 73 | return false; 74 | 75 | std::memcpy(bytes, input + offset, size); 76 | offset += size; 77 | count += size; 78 | return true; 79 | } 80 | 81 | virtual Size available () const 82 | { 83 | return length - offset; 84 | } 85 | 86 | Byte* input; 87 | Size length; 88 | Index offset; 89 | Index count ; 90 | }; 91 | 92 | //------------------------------------------------------------------------------ 93 | 94 | struct BufferInputStream : InputStream 95 | { 96 | BufferInputStream (const Buffer& buffer, Index offset = 0) 97 | : buffer(buffer) 98 | , offset(offset) 99 | , count(0) 100 | { 101 | assert(size_t(offset) < buffer.size()); 102 | } 103 | 104 | virtual bool read (Byte* bytes, Size size) 105 | { 106 | if (buffer.size() < (offset + size)) 107 | return false; 108 | 109 | std::memcpy(bytes, &buffer[offset], size); 110 | offset += size; 111 | count += size; 112 | return true; 113 | } 114 | 115 | virtual Size available () const 116 | { 117 | return buffer.size() - offset; 118 | } 119 | 120 | const Buffer& buffer; 121 | Index offset; 122 | Index count ; 123 | }; 124 | 125 | //------------------------------------------------------------------------------ 126 | 127 | struct BufferOutputStream : OutputStream 128 | { 129 | BufferOutputStream (Buffer& buffer, Index offset = 0) 130 | : buffer(buffer) 131 | , offset(offset) 132 | , count(0) 133 | { 134 | assert(size_t(offset) <= buffer.size()); 135 | } 136 | 137 | virtual bool write (const Byte* bytes, Size size) 138 | { 139 | appendBuffer(buffer, bytes, size); 140 | offset += size; 141 | count += size; 142 | return true; 143 | } 144 | 145 | Buffer& buffer; 146 | Index offset; 147 | Index count ; 148 | }; 149 | 150 | //------------------------------------------------------------------------------ 151 | 152 | class FileInputStream : public InputStream 153 | { 154 | public: 155 | explicit FileInputStream (CString path); 156 | virtual ~FileInputStream (); 157 | 158 | public: 159 | virtual bool read (Byte* bytes, Size size); 160 | 161 | private: 162 | std::ifstream input; 163 | }; 164 | 165 | //------------------------------------------------------------------------------ 166 | 167 | class FileOutputStream : public OutputStream 168 | { 169 | public: 170 | explicit FileOutputStream (CString path); 171 | virtual ~FileOutputStream (); 172 | 173 | public: 174 | virtual bool write (const Byte* bytes, Size size); 175 | 176 | private: 177 | std::ofstream output; 178 | }; 179 | 180 | //------------------------------------------------------------------------------ 181 | 182 | struct DuplexFileStream : FileInputStream, FileOutputStream 183 | { 184 | DuplexFileStream (CString input, CString output); 185 | }; 186 | 187 | } 188 | 189 | #include "./streams.hpp" 190 | -------------------------------------------------------------------------------- /headers/core/streams.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./streams.h" 8 | # include 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | inline 15 | FileInputStream::FileInputStream (CString path) 16 | : input(path) 17 | { 18 | } 19 | 20 | inline 21 | FileInputStream::~FileInputStream () 22 | { 23 | } 24 | 25 | inline bool 26 | FileInputStream::read (Byte* bytes, Size size) 27 | { 28 | do 29 | { 30 | if (!input || !input.read(reinterpret_cast(bytes), size)) 31 | return false; 32 | 33 | const int64 num = input.gcount(); 34 | 35 | size -= num; 36 | bytes += num; 37 | } 38 | while (0 < size); 39 | 40 | return true; 41 | } 42 | 43 | //------------------------------------------------------------------------------ 44 | 45 | inline 46 | FileOutputStream::FileOutputStream (CString path) 47 | : output(path) 48 | { 49 | } 50 | 51 | inline 52 | FileOutputStream::~FileOutputStream () 53 | { 54 | } 55 | 56 | inline bool 57 | FileOutputStream::write (const Byte* bytes, Size size) 58 | { 59 | if (!output || !output.write(reinterpret_cast(bytes), size)) 60 | return false; 61 | 62 | bytes += size; 63 | return true; 64 | } 65 | 66 | //------------------------------------------------------------------------------ 67 | 68 | inline 69 | DuplexFileStream::DuplexFileStream (CString input, CString output) 70 | : FileInputStream(input) 71 | , FileOutputStream(output) 72 | { 73 | 74 | } 75 | 76 | //------------------------------------------------------------------------------ 77 | 78 | } 79 | -------------------------------------------------------------------------------- /headers/core/threads.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | namespace uplink { 8 | 9 | //------------------------------------------------------------------------------ 10 | 11 | struct Mutex 12 | { 13 | Mutex () : handle(platform::CreateMutexObject()) {} 14 | ~Mutex () { platform::DestroyMutexObject(handle); } 15 | 16 | bool tryLock () { return platform::MutexTryLock(handle); } 17 | 18 | void lock () { platform::MutexLock( handle); } 19 | void unlock () { platform::MutexUnlock( handle); } 20 | 21 | platform::Mutex* handle; 22 | }; 23 | 24 | //------------------------------------------------------------------------------ 25 | 26 | class MutexLocker 27 | { 28 | public: 29 | MutexLocker (Mutex& mutex) : mutex(mutex) { mutex.lock(); } 30 | ~MutexLocker () { mutex.unlock(); } 31 | 32 | private: 33 | Mutex& mutex; 34 | }; 35 | 36 | typedef MutexLocker Locked; 37 | 38 | //------------------------------------------------------------------------------ 39 | 40 | struct Condition 41 | { 42 | Condition () : handle(platform::ConditionCreate()) {} 43 | ~Condition () { platform::ConditionDestroy(handle); } 44 | 45 | void wait (Mutex* mutex) 46 | { 47 | const MutexLocker lock(*mutex); 48 | 49 | platform::ConditionWait(handle, mutex->handle); 50 | } 51 | 52 | void signal () 53 | { 54 | platform::ConditionSignal(handle); 55 | } 56 | 57 | void broadcast () 58 | { 59 | platform::ConditionBroadcast(handle); 60 | } 61 | 62 | platform::Condition* handle; 63 | }; 64 | 65 | //------------------------------------------------------------------------------ 66 | 67 | struct Thread 68 | { 69 | public: 70 | enum Priority 71 | { 72 | PriorityLow, 73 | PriorityNormal, 74 | PriorityHigh 75 | }; 76 | 77 | public: 78 | explicit Thread (CString name = 0) 79 | : state(Stopped) 80 | , name(name) 81 | { 82 | 83 | } 84 | 85 | virtual ~Thread () 86 | { 87 | if (!isCurrentThread()) 88 | join(); 89 | } 90 | 91 | public: 92 | virtual void run () = 0; 93 | 94 | public: 95 | void start (); 96 | void stop (); 97 | void join (); 98 | void wait (); 99 | void notify (); 100 | 101 | void setPriority (Priority priority); 102 | 103 | bool isCurrentThread () const { return platform::IsCurrentThread(handle); } 104 | 105 | enum State { Stopped, Starting, Running, Stopping }; 106 | 107 | State getState () const { const MutexLocker lock (mutex); return state; } 108 | 109 | bool isStarting () const { return getState() == Starting; } 110 | bool isRunning () const { return getState() == Running ; } 111 | bool isStopping () const { return getState() == Stopping; } 112 | bool isStopped () const { return getState() == Stopped ; } 113 | 114 | public: 115 | static void sleep (float seconds) { platform::ThreadSleep(seconds); } 116 | 117 | private: 118 | static void* main (void* data); 119 | 120 | private: 121 | platform::Thread handle; 122 | mutable Mutex mutex; 123 | mutable Condition condition; 124 | State state; 125 | const CString name; 126 | }; 127 | 128 | //------------------------------------------------------------------------------ 129 | 130 | } 131 | 132 | # include "./threads.hpp" 133 | -------------------------------------------------------------------------------- /headers/core/threads.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./threads.h" 8 | # include 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | inline void 15 | Thread::start () 16 | { 17 | const MutexLocker lock (mutex); 18 | 19 | if (state != Stopped) 20 | return; 21 | 22 | state = Starting; 23 | 24 | platform::ThreadStart(&handle, main, this); 25 | } 26 | 27 | inline void 28 | Thread::stop () 29 | { 30 | const MutexLocker lock (mutex); 31 | 32 | if (state != Running) 33 | return; 34 | 35 | state = Stopping; 36 | 37 | notify(); 38 | } 39 | 40 | inline void 41 | Thread::join () 42 | { 43 | assert(!isCurrentThread()); // A thread cannot join itself. 44 | 45 | while (!isStopped()) 46 | { 47 | stop(); 48 | sleep(.001f); 49 | } 50 | } 51 | 52 | inline void 53 | Thread::wait () 54 | { 55 | condition.wait(&mutex); 56 | } 57 | 58 | inline void 59 | Thread::notify () 60 | { 61 | condition.broadcast(); 62 | } 63 | 64 | inline void 65 | Thread::setPriority (Priority priority) 66 | { 67 | switch (priority) 68 | { 69 | case PriorityLow : return platform::ThreadSetPriority(&handle, ThreadPriorityLow); 70 | case PriorityNormal: return platform::ThreadSetPriority(&handle, ThreadPriorityNormal); 71 | case PriorityHigh : return platform::ThreadSetPriority(&handle, ThreadPriorityHigh); 72 | } 73 | } 74 | 75 | inline void* 76 | Thread::main (void* data) 77 | { 78 | Thread* that = reinterpret_cast(data); 79 | 80 | # if UPLINK_HAS_APPLE 81 | if (0 != that->name) 82 | pthread_setname_np(that->name); 83 | # endif 84 | 85 | { 86 | const MutexLocker lock (that->mutex); 87 | 88 | that->state = Running; 89 | } 90 | 91 | that->run(); 92 | 93 | { 94 | const MutexLocker lock (that->mutex); 95 | 96 | that->state = Stopped; 97 | } 98 | 99 | return 0; 100 | } 101 | 102 | //------------------------------------------------------------------------------ 103 | 104 | } 105 | -------------------------------------------------------------------------------- /headers/core/types.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./config.h" 8 | # include "./macros.h" 9 | 10 | # include 11 | # include 12 | # include 13 | # include 14 | # include 15 | # include 16 | # include 17 | # include 18 | # include 19 | # include 20 | 21 | # if defined(_MSC_VER) && _MSC_VER < 1800 22 | static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff}; 23 | # define NAN (*(const float *) __nan) 24 | # define isnan _isnan 25 | # endif 26 | 27 | namespace uplink { 28 | 29 | //------------------------------------------------------------------------------ 30 | 31 | typedef uint8_t uint8; 32 | typedef uint16_t uint16; 33 | typedef uint32_t uint32; 34 | typedef uint64_t uint64; 35 | 36 | typedef int8_t int8; 37 | typedef int16_t int16; 38 | typedef int32_t int32; 39 | typedef int64_t int64; 40 | 41 | typedef uint8 Byte; 42 | typedef Byte* Bytes; 43 | 44 | typedef std::vector Buffer; 45 | 46 | typedef std::ptrdiff_t Index; 47 | typedef std::size_t Size; 48 | 49 | typedef char const* CString; 50 | typedef char* CMutableString; 51 | typedef std::string String; 52 | 53 | template < typename Type > 54 | void 55 | typed_free (Type* ptr) 56 | { 57 | std::free(ptr); 58 | } 59 | 60 | typedef std::unique_ptr CStringPtr; 61 | 62 | CStringPtr formatted (CString format, ...); 63 | String formatted_copy (CString format, ...); 64 | 65 | bool operator == (const Buffer& buffer, const String& string); 66 | bool operator == (const String& string, const Buffer& buffer); 67 | 68 | typedef std::list Strings; 69 | 70 | enum Ownership 71 | { 72 | NoOwnership, 73 | SelfOwnership, 74 | SharedOwnership 75 | }; 76 | 77 | inline void 78 | uplink_swap(Ownership& first, Ownership& second) 79 | { 80 | ::std::swap(first, second); 81 | } 82 | 83 | //------------------------------------------------------------------------------ 84 | 85 | template < typename Type > 86 | inline String 87 | toString (const Type& instance) 88 | { 89 | return instance.toString(); 90 | } 91 | 92 | # define UPLINK_PRINTABLE_TYPE(Type, Format) \ 93 | inline String \ 94 | toString (const Type& value) \ 95 | { \ 96 | return formatted_copy(Format, value); \ 97 | } 98 | 99 | UPLINK_PRINTABLE_TYPE(uint8 , "%d") 100 | UPLINK_PRINTABLE_TYPE(uint16, "%d") 101 | UPLINK_PRINTABLE_TYPE(uint32, "%d") 102 | UPLINK_PRINTABLE_TYPE(uint64, "%d") 103 | UPLINK_PRINTABLE_TYPE( int8 , "%d") 104 | UPLINK_PRINTABLE_TYPE( int16, "%d") 105 | UPLINK_PRINTABLE_TYPE( int32, "%d") 106 | UPLINK_PRINTABLE_TYPE( int64, "%d") 107 | UPLINK_PRINTABLE_TYPE(bool , "%d") 108 | UPLINK_PRINTABLE_TYPE(float , "%f") 109 | UPLINK_PRINTABLE_TYPE(double, "%f") 110 | 111 | //------------------------------------------------------------------------------ 112 | 113 | template < typename T > 114 | inline bool modified (T& lhs, const T& rhs) 115 | { 116 | const bool ret = lhs != rhs; 117 | 118 | lhs = rhs; 119 | 120 | return ret; 121 | } 122 | 123 | template < class Class > 124 | struct Clonable 125 | { 126 | virtual ~Clonable () {} 127 | 128 | virtual Class* clone () const = 0; 129 | }; 130 | 131 | 132 | template < class Derived, class Base > 133 | inline Derived* 134 | downcast (Base* base) 135 | { 136 | #ifndef DEBUG 137 | return static_cast(base); 138 | #else 139 | Derived* const derived = dynamic_cast(base); 140 | assert(0 != derived); 141 | return derived; 142 | #endif 143 | } 144 | 145 | inline String 146 | prettyByteSize (double size) 147 | { 148 | const char* suffixes [] = { " ", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; 149 | int n = 0; 150 | while (size > 1024 && n < sizeof_array(suffixes)) 151 | { 152 | size /= 1024; 153 | ++n; 154 | } 155 | return formatted_copy("%7.2f %s", size, suffixes[n]); 156 | } 157 | 158 | inline String 159 | prettyByteSize (size_t size) 160 | { 161 | return prettyByteSize(double(size)); 162 | } 163 | 164 | //------------------------------------------------------------------------------ 165 | 166 | } 167 | 168 | # include "./types.hpp" 169 | -------------------------------------------------------------------------------- /headers/core/types.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./types.h" 8 | 9 | # if UPLINK_HAS_CXX11 || _MSC_VER >= 1600 || (__APPLE__ && !__GLIBCXX__) 10 | # include 11 | # define uplink_ref ::std::shared_ptr 12 | # else 13 | # include 14 | # define uplink_ref ::std::tr1::shared_ptr 15 | # endif 16 | 17 | namespace uplink { 18 | 19 | int vasprintf (char** output, const char* format, va_list args); 20 | 21 | //------------------------------------------------------------------------------ 22 | 23 | // Somebody explain me what's going on with std::swap and C++11. 24 | // 25 | // This code breaks std::vector::swap instantiations with clang & libc++: 26 | // 27 | // template < typename Type > 28 | // void swap (Type& first, Type& second) 29 | // {} 30 | // 31 | // So, for now, let's use: 'uplink_swap(a,b)' and 'a.swapWith(b)'. 32 | 33 | # define UPLINK_SWAPPABLE_TYPE(Type) \ 34 | inline void \ 35 | uplink_swap (Type& first, Type& second) \ 36 | { \ 37 | ::std::swap(first, second); \ 38 | } 39 | 40 | UPLINK_SWAPPABLE_TYPE(void*) 41 | UPLINK_SWAPPABLE_TYPE(bool) 42 | UPLINK_SWAPPABLE_TYPE(uint8) 43 | UPLINK_SWAPPABLE_TYPE(uint16) 44 | UPLINK_SWAPPABLE_TYPE(uint32) 45 | UPLINK_SWAPPABLE_TYPE(uint64) 46 | UPLINK_SWAPPABLE_TYPE(int8) 47 | UPLINK_SWAPPABLE_TYPE(int16) 48 | UPLINK_SWAPPABLE_TYPE(int32) 49 | UPLINK_SWAPPABLE_TYPE(int64) 50 | UPLINK_SWAPPABLE_TYPE(float) 51 | UPLINK_SWAPPABLE_TYPE(double) 52 | UPLINK_SWAPPABLE_TYPE(std::string) 53 | #if __APPLE__ 54 | UPLINK_SWAPPABLE_TYPE(size_t) 55 | #endif 56 | 57 | # undef UPLINK_SWAPPABLE_TYPE 58 | 59 | template < class Class > 60 | inline void 61 | uplink_swap (Class*& first, Class*& second) 62 | { 63 | std::swap(first, second); 64 | } 65 | 66 | template < class Class > 67 | inline void 68 | uplink_swap (const Class*& first, const Class*& second) 69 | { 70 | std::swap(first, second); 71 | } 72 | 73 | template < class Class > 74 | inline void 75 | uplink_swap (uplink_ref& first, uplink_ref& second) 76 | { 77 | first.swap(second); 78 | } 79 | 80 | template < class Class > 81 | inline void 82 | uplink_swap (std::vector& first, std::vector& second) 83 | { 84 | first.swap(second); 85 | } 86 | 87 | template < class Class > 88 | inline void 89 | uplink_swap (Class& first, Class& second) 90 | { 91 | first.swapWith(second); 92 | } 93 | 94 | inline CStringPtr 95 | formatted (CString format, ...) 96 | { 97 | char* buf; 98 | va_list args; 99 | va_start(args, format); 100 | vasprintf(&buf, format, args); 101 | va_end(args); 102 | return CStringPtr(buf, typed_free); 103 | } 104 | 105 | inline String 106 | formatted_copy (CString format, ...) 107 | { 108 | char* buf; 109 | va_list args; 110 | va_start(args, format); 111 | vasprintf(&buf, format, args); 112 | va_end(args); 113 | CStringPtr freed(buf, typed_free); 114 | return String(freed.get()); 115 | } 116 | 117 | inline bool 118 | operator == (const Buffer& buffer, const String& string) 119 | { 120 | return std::equal(buffer.begin(), buffer.end(), string.begin()); 121 | } 122 | 123 | inline bool 124 | operator == (const String& string, const Buffer& buffer) 125 | { 126 | return buffer == string; 127 | } 128 | 129 | //------------------------------------------------------------------------------ 130 | 131 | } 132 | -------------------------------------------------------------------------------- /headers/core/wires.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "../message.h" 8 | # include "./threads.h" 9 | 10 | namespace uplink { 11 | 12 | struct Endpoint; 13 | 14 | //------------------------------------------------------------------------------ 15 | 16 | class Wire 17 | { 18 | public: 19 | Wire (DuplexStream* stream, Endpoint* endpoint); 20 | ~Wire (); 21 | 22 | public: 23 | void start (); 24 | void stop (); 25 | 26 | void notifySender (); 27 | void notifyReceiver (); 28 | 29 | public: 30 | bool isConnected () const 31 | { 32 | return 33 | !sender .isDisconnected() 34 | && !receiver.isDisconnected(); 35 | } 36 | 37 | private: 38 | struct Loop : Thread 39 | { 40 | Loop (Wire* that, CString name); 41 | 42 | virtual void run (); 43 | 44 | virtual void loop () = 0; 45 | 46 | bool isDisconnected () const { const MutexLocker _(mutex); return disconnected; } 47 | 48 | Wire* that; 49 | 50 | private: 51 | mutable Mutex mutex; 52 | bool disconnected; 53 | }; 54 | 55 | struct Receiver : Loop 56 | { 57 | Receiver (Wire* that) : Loop(that, "uplink::Wire::Receiver") {} 58 | 59 | virtual void loop (); 60 | }; 61 | 62 | private: 63 | struct Sender : Loop 64 | { 65 | Sender (Wire* that) : Loop(that, "uplink::Wire::Sender") {} 66 | 67 | virtual void loop (); 68 | 69 | private: 70 | StopWatch keepAliveStopWatch; 71 | }; 72 | 73 | private: 74 | DuplexStream* stream; 75 | Endpoint* endpoint; 76 | MessageSerializer serializer; 77 | Sender sender; 78 | Receiver receiver; 79 | }; 80 | 81 | //------------------------------------------------------------------------------ 82 | 83 | } 84 | 85 | // We can't include the inline definitions from here. 86 | // See: endpoints.h. 87 | // # include "./wires.hpp" 88 | -------------------------------------------------------------------------------- /headers/core/wires.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./wires.h" 8 | # include "../endpoints.h" 9 | # include "./threads.h" 10 | # include "./macros.h" 11 | 12 | namespace uplink { 13 | 14 | //------------------------------------------------------------------------------ 15 | 16 | inline 17 | Wire::Wire (DuplexStream* stream, Endpoint* endpoint) 18 | : stream(stream) 19 | , endpoint(endpoint) 20 | , sender(this) 21 | , receiver(this) 22 | { 23 | assert(0 != stream); 24 | assert(0 != endpoint); 25 | 26 | endpoint->wire = this; 27 | } 28 | 29 | inline 30 | Wire::~Wire () 31 | { 32 | stop(); 33 | } 34 | 35 | inline void 36 | Wire::start () 37 | { 38 | endpoint->registerMessages(serializer); 39 | 40 | receiver.start(); 41 | sender.start(); 42 | } 43 | 44 | inline void 45 | Wire::stop () 46 | { 47 | TCPConnection* connection = dynamic_cast(stream); 48 | if (0 != connection) 49 | connection->disconnecting = true; 50 | 51 | receiver.join(); 52 | sender.join(); 53 | 54 | delete connection; 55 | stream = 0; 56 | } 57 | 58 | inline void 59 | Wire::notifySender () 60 | { 61 | sender.notify(); 62 | } 63 | 64 | inline void 65 | Wire::notifyReceiver () 66 | { 67 | sender.notify(); 68 | } 69 | 70 | //------------------------------------------------------------------------------ 71 | 72 | inline 73 | Wire::Loop::Loop (Wire* that, CString name) 74 | : Thread(name) 75 | , that(that) 76 | , disconnected(false) 77 | { 78 | assert(0 != that); 79 | } 80 | 81 | inline void 82 | Wire::Loop::run () 83 | { 84 | loop(); 85 | 86 | if (that->isConnected()) // Then no other loop has disconnected the endpoint, yet. 87 | { 88 | { 89 | const MutexLocker _(mutex); 90 | 91 | disconnected = true; // Which will prevent other running loops from getting there on disconnection. 92 | } 93 | 94 | that->endpoint->disconnected(); 95 | that->endpoint->reset(); 96 | } 97 | } 98 | 99 | //------------------------------------------------------------------------------ 100 | 101 | inline void 102 | Wire::Receiver::loop () 103 | { 104 | MessageInput messageInput(*that->stream, that->serializer); 105 | 106 | while (isRunning()) 107 | { 108 | Message* message = messageInput.readMessage(); 109 | 110 | report_unless("cannot read network message", 0 != message); 111 | 112 | if (MessageKind_KeepAlive == message->kind()) 113 | continue; // In effect ignoring the keep-alive message. 114 | 115 | uplink_log_debug("Message received: %s (session: %d)", message->name(), message->sessionId); 116 | 117 | report_unless("cannot receive network message", that->endpoint->receiveMessage(message)); 118 | } 119 | } 120 | 121 | //------------------------------------------------------------------------------ 122 | 123 | inline void 124 | Wire::Sender::loop () 125 | { 126 | MessageOutput messageOutput(*that->stream, that->serializer); 127 | 128 | while (isRunning()) 129 | { 130 | bool sent = false; 131 | 132 | report_unless("cannot send network messages", that->endpoint->sendMessages(messageOutput, sent)); 133 | 134 | if (sent) 135 | { 136 | keepAliveStopWatch.start(); 137 | } 138 | else 139 | { 140 | static const double maxKeepAliveAge = 1.; 141 | 142 | const double keepAliveAge = keepAliveStopWatch.elapsed(); 143 | 144 | if (maxKeepAliveAge < keepAliveAge) 145 | { 146 | KeepAlive keepAlive; 147 | keepAlive.sessionId = SystemSessionId; 148 | 149 | report_unless("cannot send keep-alive message", messageOutput.writeMessage(keepAlive)); 150 | 151 | keepAliveStopWatch.start(); 152 | } 153 | else 154 | { 155 | sleep(.001f); // Avoid active loops. 156 | } 157 | } 158 | 159 | // FIXME: Rework sender thread notifications. 160 | } 161 | } 162 | 163 | //------------------------------------------------------------------------------ 164 | 165 | } 166 | -------------------------------------------------------------------------------- /headers/desktop-server.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./servers.h" 8 | 9 | namespace uplink { 10 | 11 | struct DesktopUI; 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | struct DesktopServer : Server 16 | { 17 | public: 18 | DesktopServer (const std::string& serviceName, int servicePort, objc_weak ServerDelegate* serverDelegate); 19 | ~DesktopServer (); 20 | 21 | public: 22 | DesktopServerUI& ui() { return *_ui; } 23 | 24 | private: 25 | DesktopServerUI* _ui; 26 | }; 27 | 28 | //------------------------------------------------------------------------------ 29 | 30 | struct DesktopServerSession : ServerSession 31 | { 32 | DesktopServerSession (int socketDescriptor, Server* server) 33 | : ServerSession(socketDescriptor, server) 34 | { 35 | 36 | } 37 | 38 | DesktopServer& server () { return *downcast(&ServerSession::server()); } 39 | }; 40 | 41 | //------------------------------------------------------------------------------ 42 | 43 | } // uplink namespace 44 | 45 | # include "./desktop-server.hpp" 46 | -------------------------------------------------------------------------------- /headers/desktop-server.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # include "./desktop-server.h" 6 | 7 | # if UPLINK_HAS_DESKTOP_UI 8 | # include "./desktop-ui.h" 9 | # endif 10 | 11 | namespace uplink { 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | inline 16 | DesktopServer::DesktopServer (const std::string& serviceName, int servicePort, objc_weak ServerDelegate* serverDelegate) 17 | : Server(serviceName, servicePort, serverDelegate) 18 | , _ui(0) 19 | { 20 | # if UPLINK_HAS_DESKTOP_UI 21 | _ui = new DesktopServerUI; 22 | # endif 23 | } 24 | 25 | inline 26 | DesktopServer::~DesktopServer () 27 | { 28 | Server::clear(); 29 | 30 | // No other threads should call us back, now. 31 | 32 | # if UPLINK_HAS_DESKTOP_UI 33 | zero_delete(_ui); 34 | # endif 35 | } 36 | 37 | //------------------------------------------------------------------------------ 38 | 39 | } // uplink namespace 40 | -------------------------------------------------------------------------------- /headers/desktop-ui.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/types.h" 8 | 9 | namespace uplink { 10 | 11 | struct DesktopServerUI 12 | { 13 | DesktopServerUI(); 14 | ~DesktopServerUI(); 15 | 16 | void run (); 17 | 18 | void setColorImage(const uint8* buffer, int width, int height); 19 | void setDepthImage(const uint16* buffer, int width, int height); 20 | 21 | struct Impl; 22 | Impl* impl; 23 | }; 24 | 25 | } // uplink namespace 26 | 27 | # include "./desktop-ui.hpp" 28 | -------------------------------------------------------------------------------- /headers/discovery.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./services.h" 8 | # include "./core/datagrams.h" 9 | # include "./core/threads.h" 10 | # include 11 | # include 12 | 13 | namespace uplink { 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | # define UPLINK_SERVICE_DISCOVERY_DATAGRAM_MAGIC "^l1nk" 18 | # define UPLINK_SERVICE_DISCOVERY_DATAGRAM_MAGIC_LENGTH sizeof_array(UPLINK_SERVICE_DISCOVERY_DATAGRAM_MAGIC) 19 | # define UPLINK_SERVICE_DISCOVERY_DATAGRAM_LENGTH 512 20 | 21 | //------------------------------------------------------------------------------ 22 | 23 | struct ServicePublisher : public Thread 24 | { 25 | ServicePublisher (uint16 udpport, bool autoStart = false); 26 | 27 | ~ServicePublisher (); 28 | 29 | void setBroadcastingEnabled (bool enabled); 30 | 31 | virtual void run (); 32 | 33 | uint16 udpport; 34 | std::vector serviceList; 35 | bool broadcastingEnabled; 36 | }; 37 | 38 | //------------------------------------------------------------------------------ 39 | 40 | struct ServiceFinder : public Thread 41 | { 42 | ServiceFinder (uint16 port, bool autostart = true); 43 | 44 | virtual ~ServiceFinder (); 45 | 46 | virtual void run (); 47 | 48 | virtual void onServiceDiscovered (const Service& service) = 0; 49 | 50 | uint16 port; 51 | }; 52 | 53 | //------------------------------------------------------------------------------ 54 | 55 | } 56 | 57 | # include "./discovery.hpp" 58 | -------------------------------------------------------------------------------- /headers/image-codecs.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./image-codecs.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | } 16 | -------------------------------------------------------------------------------- /headers/image.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./blobs.h" 8 | # include "./camera-calibration.h" 9 | # include 10 | 11 | # if __APPLE__ 12 | # include 13 | # include 14 | # endif 15 | 16 | namespace uplink { 17 | 18 | //------------------------------------------------------------------------------ 19 | 20 | UPLINK_ENUM_BEGIN(ImageFormat) 21 | 22 | ImageFormat_Empty, 23 | 24 | ImageFormat_Shifts, 25 | ImageFormat_CompressedShifts, 26 | 27 | ImageFormat_Gray, // FIXME: Implement 28 | 29 | ImageFormat_RGB, 30 | ImageFormat_YCbCr, 31 | ImageFormat_JPEG, 32 | ImageFormat_H264, 33 | 34 | UPLINK_ENUM_END(ImageFormat) 35 | 36 | inline bool 37 | isValidImageFormat (ImageFormat imageFormat) 38 | { 39 | return ImageFormat_Invalid < imageFormat && imageFormat < ImageFormat_HowMany; 40 | } 41 | 42 | //------------------------------------------------------------------------------ 43 | 44 | struct Image : Message 45 | { 46 | public: 47 | UPLINK_MESSAGE_CLASS(Image); 48 | 49 | enum { MaxNumPlanes = 2 }; 50 | 51 | public: 52 | Image (); 53 | Image (const Image& copy); 54 | 55 | public: 56 | struct Shifts {}; 57 | struct CompressedShifts {}; 58 | 59 | public: 60 | Image (uint16* shifts, size_t size, Shifts); 61 | Image (uint8* shifts, size_t size, CompressedShifts); 62 | 63 | public: 64 | ~Image (); 65 | 66 | Image& operator = (const Image& other); 67 | 68 | void clear (); 69 | 70 | void swapWith (Image& other); 71 | 72 | virtual bool serializeWith (Serializer& s); 73 | 74 | public: 75 | bool isEmpty () const 76 | { 77 | return 0 == width * height; 78 | } 79 | 80 | bool isCompressed () const 81 | { 82 | return 83 | ImageFormat_CompressedShifts == format 84 | || ImageFormat_JPEG == format 85 | || ImageFormat_H264 == format 86 | ; 87 | } 88 | 89 | bool isCompressedOrEmpty () const 90 | { 91 | return isEmpty() || isCompressed(); 92 | } 93 | 94 | # if __APPLE__ 95 | public: 96 | Image (CMSampleBufferRef sampleBuffer, const CameraInfo& cameraInfo_, size_t width = 0, size_t height = 0); 97 | Image (CVPixelBufferRef pixelBuffer, const CameraInfo& cameraInfo_); 98 | 99 | private: 100 | void initializeWithPixelBuffer_RGB (CVPixelBufferRef pixelBuffer); 101 | void initializeWithPixelBuffer_YCbCr (CVPixelBufferRef pixelBuffer); 102 | void initializeWithBlockBuffer (CMBlockBufferRef blockBuffer, ImageFormat format_, size_t width, size_t height); 103 | 104 | public: 105 | CVPixelBufferRef pixelBuffer () const; 106 | CMBlockBufferRef blockBuffer () const; 107 | # endif 108 | 109 | public: // For now. 110 | struct Storage 111 | { 112 | Storage (); 113 | 114 | enum Type 115 | { 116 | Type_Invalid, 117 | 118 | # if __APPLE__ 119 | Type_BlockBuffer, 120 | Type_PixelBuffer, 121 | # endif 122 | }; 123 | 124 | union Handle 125 | { 126 | void* invalid; 127 | 128 | # if __APPLE__ 129 | CMBlockBufferRef blockBuffer; 130 | CVPixelBufferRef pixelBuffer; 131 | # endif 132 | }; 133 | 134 | Type type; 135 | Handle handle; 136 | }; 137 | 138 | public: // For now. 139 | struct Plane 140 | { 141 | void* buffer; 142 | size_t sizeInBytes; 143 | size_t bytesPerRow; 144 | }; 145 | 146 | ImageFormat format; 147 | size_t width; 148 | size_t height; 149 | Plane planes[MaxNumPlanes]; 150 | CameraInfo cameraInfo; 151 | std::function release; 152 | std::function retain; 153 | Storage storage; 154 | Blobs attachments; 155 | }; 156 | 157 | //------------------------------------------------------------------------------ 158 | 159 | } 160 | 161 | # include "./image.hpp" 162 | -------------------------------------------------------------------------------- /headers/messages.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./message.h" 8 | # include "./motion.h" 9 | # include "./camera-frame.h" 10 | # include "./camera-pose.h" 11 | # include 12 | 13 | namespace uplink { 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | struct KeepAlive : Message 18 | { 19 | UPLINK_MESSAGE_CLASS(KeepAlive) 20 | 21 | virtual bool serializeWith (Serializer &serializer) 22 | { 23 | return true; // Nothing to read or write, there. 24 | } 25 | }; 26 | 27 | //------------------------------------------------------------------------------ 28 | 29 | // FIXME: Move this where it belongs. 30 | 31 | UPLINK_ENUM_BEGIN(SessionSetupStatus) 32 | SessionSetupStatus_Success, 33 | SessionSetupStatus_Failure, 34 | // FIXME: SessionSetupStatus_Failure_ColorUnavailable, 35 | UPLINK_ENUM_END(SessionSetupStatus) 36 | 37 | struct SessionSetupReply : Message 38 | { 39 | UPLINK_MESSAGE_CLASS(SessionSetupReply) 40 | 41 | enum { MaxLength = 0xffff }; // FIXME: Factor out short strings. 42 | 43 | SessionSetupReply () 44 | : remoteSessionId(InvalidSessionId) 45 | , status(SessionSetupStatus_Failure) 46 | , message() 47 | { 48 | } 49 | 50 | SessionSetupReply (SessionId remoteSessionId, SessionSetupStatus status, String message = "") 51 | : remoteSessionId(remoteSessionId) 52 | , status(status) 53 | , message(message) 54 | { 55 | } 56 | 57 | void swapWith (SessionSetupReply& other) 58 | { 59 | Message::swapWith(other); 60 | 61 | uplink_swap(remoteSessionId, other.remoteSessionId); 62 | uplink_swap(status , other.status); 63 | uplink_swap(message , other.message); 64 | } 65 | 66 | virtual bool serializeWith (Serializer& s) 67 | { 68 | return_false_unless(s.put(remoteSessionId)); 69 | 70 | return_false_unless(s.put(status)); 71 | 72 | if (s.isReader()) 73 | return s.asReader().readString(message, MaxLength); 74 | else 75 | return s.asWriter().writeString(message, MaxLength); 76 | } 77 | 78 | SessionId remoteSessionId; 79 | SessionSetupStatus status; 80 | String message; 81 | }; 82 | 83 | //------------------------------------------------------------------------------ 84 | 85 | namespace { // FIXME: Move this where it belongs. 86 | 87 | struct NonPrintableFilter 88 | { 89 | NonPrintableFilter (char replacement = '?') : replacement(replacement) {} 90 | 91 | char operator () (char c) const { return 0 < c ? (std::isprint(c) ? c : replacement) : replacement; } 92 | 93 | char replacement; 94 | }; 95 | 96 | } 97 | 98 | //------------------------------------------------------------------------------ 99 | 100 | struct CustomCommand : Message 101 | { 102 | UPLINK_MESSAGE_CLASS(CustomCommand) 103 | 104 | enum { MaxLength = 0xffff }; // FIXME: Factor out short strings. 105 | 106 | CustomCommand () 107 | {} 108 | 109 | CustomCommand (const String& command_) 110 | : command(command_) 111 | { 112 | assert(command.size() < size_t(MaxLength)); 113 | } 114 | 115 | CustomCommand (CString command_) 116 | : command(command_) 117 | { 118 | assert(command.size() < size_t(MaxLength)); 119 | } 120 | 121 | void swapWith (CustomCommand& other) 122 | { 123 | Message::swapWith(other); 124 | 125 | uplink_swap(other.command, command); 126 | } 127 | 128 | virtual bool serializeWith (Serializer& s) 129 | { 130 | if (s.isReader()) 131 | return s.asReader().readString(command, MaxLength); 132 | else 133 | return s.asWriter().writeString(command, MaxLength); 134 | } 135 | 136 | virtual String toString () const 137 | { 138 | // Commands might be very long and contain zeroes and binary data. 139 | 140 | static const size_t maxLength = 256; 141 | 142 | String ret(command, 0, maxLength); 143 | 144 | std::transform(ret.begin(), ret.end(), ret.begin(), NonPrintableFilter()); 145 | 146 | return ret; 147 | } 148 | 149 | String command; 150 | }; 151 | 152 | //------------------------------------------------------------------------------ 153 | 154 | } 155 | 156 | # include "./messages.hpp" 157 | -------------------------------------------------------------------------------- /headers/messages.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./messages.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | } 16 | -------------------------------------------------------------------------------- /headers/motion.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/enum.h" 8 | # include "./core/serializers.h" 9 | 10 | namespace uplink { 11 | 12 | //------------------------------------------------------------------------------ 13 | 14 | // The following C++ types are modeled after the Objective-C types defined in Apple's CoreMotion framework. 15 | // See: http://developer.apple.com/library/ios/documentation/CoreMotion/Reference/CoreMotion_Reference 16 | 17 | //------------------------------------------------------------------------------ 18 | 19 | struct Attitude : Serializable 20 | { 21 | // Quaternion. 22 | double x; 23 | double y; 24 | double z; 25 | double w; 26 | 27 | // Matrix 28 | double m11, m12, m13; 29 | double m21, m22, m23; 30 | double m31, m32, m33; 31 | 32 | void swapWith (Attitude& other); 33 | 34 | virtual bool serializeWith (Serializer& serializer); 35 | }; 36 | 37 | //------------------------------------------------------------------------------ 38 | 39 | struct RotationRate : Serializable 40 | { 41 | double x; 42 | double y; 43 | double z; 44 | 45 | void swapWith (RotationRate& other); 46 | 47 | virtual bool serializeWith (Serializer& serializer); 48 | }; 49 | 50 | //------------------------------------------------------------------------------ 51 | 52 | struct Acceleration : Serializable 53 | { 54 | double x; 55 | double y; 56 | double z; 57 | 58 | void swapWith (Acceleration& other); 59 | 60 | virtual bool serializeWith (Serializer& serializer); 61 | }; 62 | 63 | //------------------------------------------------------------------------------ 64 | 65 | struct MagneticField : Serializable 66 | { 67 | UPLINK_ENUM_BEGIN(Accuracy) 68 | Accuracy_Uncalibrated, 69 | Accuracy_Low, 70 | Accuracy_Medium, 71 | Accuracy_High, 72 | UPLINK_ENUM_END(Accuracy) 73 | 74 | double x; 75 | double y; 76 | double z; 77 | 78 | Accuracy accuracy; 79 | 80 | void swapWith (MagneticField& other); 81 | 82 | virtual bool serializeWith (Serializer& serializer); 83 | }; 84 | 85 | //------------------------------------------------------------------------------ 86 | 87 | struct DeviceMotion : Serializable 88 | { 89 | Attitude attitude; 90 | RotationRate rotationRate; 91 | Acceleration gravity; 92 | Acceleration userAcceleration; 93 | MagneticField magneticField; 94 | 95 | void swapWith (DeviceMotion& other); 96 | 97 | virtual bool serializeWith (Serializer& serializer); 98 | }; 99 | 100 | //------------------------------------------------------------------------------ 101 | 102 | struct Event : Message 103 | { 104 | Event () 105 | {} 106 | 107 | Event (double timestamp) 108 | : timestamp(timestamp) 109 | { 110 | } 111 | 112 | void swapWith (Event& other) 113 | { 114 | Message::swapWith(other); 115 | uplink_swap(timestamp, other.timestamp); 116 | } 117 | 118 | virtual bool serializeWith (Serializer& serializer); 119 | 120 | double timestamp; 121 | }; 122 | 123 | //------------------------------------------------------------------------------ 124 | 125 | template < class Type > 126 | struct UnaryEvent : Event 127 | { 128 | virtual MessageKind kind () const; 129 | 130 | virtual Message* clone () const; 131 | 132 | UnaryEvent () 133 | {} 134 | 135 | UnaryEvent (const UnaryEvent& copy) 136 | : Event(copy.timestamp) 137 | , value(copy.value) 138 | {} 139 | 140 | UnaryEvent (double timestamp, const Type& value) 141 | : Event(timestamp) 142 | , value(value) 143 | {} 144 | 145 | Type value; 146 | 147 | void swapWith (UnaryEvent& other); 148 | 149 | virtual bool serializeWith (Serializer& serializer); 150 | }; 151 | 152 | //------------------------------------------------------------------------------ 153 | 154 | typedef UnaryEvent GyroscopeEvent; 155 | typedef UnaryEvent AccelerometerEvent; 156 | typedef UnaryEvent DeviceMotionEvent; 157 | 158 | //------------------------------------------------------------------------------ 159 | 160 | } 161 | 162 | # include "./motion.hpp" 163 | -------------------------------------------------------------------------------- /headers/motion.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./motion.h" 8 | # include "./core/macros.h" 9 | # include "./core/serializers.h" 10 | 11 | namespace uplink { 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | # define MEMBERS() \ 16 | MEMBER(x) \ 17 | MEMBER(y) \ 18 | MEMBER(z) \ 19 | MEMBER(w) \ 20 | MEMBER(m11) \ 21 | MEMBER(m12) \ 22 | MEMBER(m13) \ 23 | MEMBER(m21) \ 24 | MEMBER(m22) \ 25 | MEMBER(m23) \ 26 | MEMBER(m31) \ 27 | MEMBER(m32) \ 28 | MEMBER(m33) 29 | 30 | inline void 31 | Attitude::swapWith (Attitude& other) 32 | { 33 | # define MEMBER(Name) uplink_swap(Name, other.Name); 34 | MEMBERS() 35 | # undef MEMBER 36 | } 37 | 38 | inline bool 39 | Attitude::serializeWith (Serializer& s) 40 | { 41 | # define MEMBER(Name) report_false_unless("Cannot archive Attitude::" #Name, s.put(Name)); 42 | MEMBERS() 43 | # undef MEMBER 44 | 45 | return true; 46 | } 47 | 48 | # undef MEMBERS 49 | 50 | //------------------------------------------------------------------------------ 51 | 52 | # define MEMBERS() \ 53 | MEMBER(x) \ 54 | MEMBER(y) \ 55 | MEMBER(z) 56 | 57 | inline void 58 | RotationRate::swapWith (RotationRate& other) 59 | { 60 | # define MEMBER(Name) uplink_swap(Name, other.Name); 61 | MEMBERS() 62 | # undef MEMBER 63 | } 64 | 65 | inline bool 66 | RotationRate::serializeWith (Serializer& s) 67 | { 68 | # define MEMBER(Name) report_false_unless("Cannot archive RotationRate::" #Name, s.put(Name)); 69 | MEMBERS() 70 | # undef MEMBER 71 | 72 | return true; 73 | } 74 | 75 | # undef MEMBERS 76 | 77 | //------------------------------------------------------------------------------ 78 | 79 | # define MEMBERS() \ 80 | MEMBER(x) \ 81 | MEMBER(y) \ 82 | MEMBER(z) 83 | 84 | inline void 85 | Acceleration::swapWith (Acceleration& other) 86 | { 87 | # define MEMBER(Name) uplink_swap(Name, other.Name); 88 | MEMBERS() 89 | # undef MEMBER 90 | } 91 | 92 | inline bool 93 | Acceleration::serializeWith (Serializer& s) 94 | { 95 | # define MEMBER(Name) report_false_unless("Cannot archive Acceleration::" #Name, s.put(Name)); 96 | MEMBERS() 97 | # undef MEMBER 98 | 99 | return true; 100 | } 101 | 102 | # undef MEMBERS 103 | 104 | //------------------------------------------------------------------------------ 105 | 106 | # define MEMBERS() \ 107 | MEMBER(x) \ 108 | MEMBER(y) \ 109 | MEMBER(z) \ 110 | MEMBER(accuracy) 111 | 112 | inline void 113 | MagneticField::swapWith (MagneticField& other) 114 | { 115 | # define MEMBER(Name) uplink_swap(Name, other.Name); 116 | MEMBERS() 117 | # undef MEMBER 118 | } 119 | 120 | inline bool 121 | MagneticField::serializeWith (Serializer& s) 122 | { 123 | # define MEMBER(Name) report_false_unless("cannot archive MagneticField::" #Name, s.put(Name)); 124 | MEMBERS() 125 | # undef MEMBER 126 | 127 | return true; 128 | } 129 | 130 | # undef MEMBERS 131 | 132 | //------------------------------------------------------------------------------ 133 | 134 | # define MEMBERS() \ 135 | MEMBER(attitude) \ 136 | MEMBER(rotationRate) \ 137 | MEMBER(gravity) \ 138 | MEMBER(userAcceleration) \ 139 | MEMBER(magneticField) 140 | 141 | inline void 142 | DeviceMotion::swapWith (DeviceMotion& other) 143 | { 144 | # define MEMBER(Name) uplink_swap(Name, other.Name); 145 | MEMBERS() 146 | # undef MEMBER 147 | } 148 | 149 | inline bool 150 | DeviceMotion::serializeWith (Serializer& s) 151 | { 152 | # define MEMBER(Name) report_false_unless("cannot archive DeviceMotion::" #Name, s.put(Name)); 153 | MEMBERS() 154 | # undef MEMBER 155 | 156 | return true; 157 | } 158 | 159 | # undef MEMBERS 160 | 161 | //------------------------------------------------------------------------------ 162 | 163 | template <> inline MessageKind UnaryEvent::kind () const { return MessageKind_GyroscopeEvent; } 164 | template <> inline MessageKind UnaryEvent::kind () const { return MessageKind_AccelerometerEvent; } 165 | template <> inline MessageKind UnaryEvent::kind () const { return MessageKind_DeviceMotionEvent; } 166 | 167 | template <> inline Message* UnaryEvent::clone () const { return new UnaryEvent(*this); } 168 | template <> inline Message* UnaryEvent::clone () const { return new UnaryEvent(*this); } 169 | template <> inline Message* UnaryEvent::clone () const { return new UnaryEvent(*this); } 170 | 171 | 172 | //------------------------------------------------------------------------------ 173 | 174 | inline bool 175 | Event::serializeWith (Serializer& s) 176 | { 177 | report_false_unless("cannot archive imu event timestamp", s.put(timestamp)); 178 | 179 | return true; 180 | } 181 | 182 | //------------------------------------------------------------------------------ 183 | 184 | # define UNARY_EVENT_METHOD(...) \ 185 | template < class Type > \ 186 | inline __VA_ARGS__ \ 187 | UnaryEvent:: 188 | 189 | UNARY_EVENT_METHOD(void) 190 | swapWith (UnaryEvent& other) 191 | { 192 | Event::swapWith(other); 193 | 194 | uplink_swap(value, other.value); 195 | } 196 | 197 | UNARY_EVENT_METHOD(bool) 198 | serializeWith (Serializer& s) 199 | { 200 | return_false_unless(Event::serializeWith(s)); 201 | 202 | report_false_unless("cannot archive imu event value", s.put(value)); 203 | 204 | return true; 205 | } 206 | # undef UNARY_EVENT_METHOD 207 | 208 | //------------------------------------------------------------------------------ 209 | 210 | } 211 | -------------------------------------------------------------------------------- /headers/servers.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./endpoints.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | class Server; 14 | class ServerDelegate; 15 | struct DesktopServerUI; 16 | 17 | //------------------------------------------------------------------------------ 18 | 19 | struct ServerSession : Endpoint 20 | { 21 | public: 22 | ServerSession (int socketDescriptor, Server* server); 23 | 24 | void start (); 25 | void stop (); 26 | 27 | virtual void disconnected (); 28 | virtual void onSessionSetup (const SessionSetup& sessionSetup); 29 | 30 | virtual void onRemoteSessionSetupSuccess () 31 | { 32 | uplink_log_info("Remote session setup successful."); 33 | } 34 | 35 | virtual void onRemoteSessionSetupFailure () 36 | { 37 | uplink_log_error("Remote session setup failed."); 38 | } 39 | 40 | Server& server() { return *_server; } 41 | 42 | private: 43 | int _socketDescriptor; 44 | Wire* _wire; 45 | Server* _server; 46 | 47 | virtual void onVersionInfo (const VersionInfo& clientVersionInfo) 48 | { 49 | uplink_log_info("Client version: %i.%i", clientVersionInfo.major, clientVersionInfo.minor); 50 | 51 | // Nothing else to do, for now. 52 | } 53 | 54 | virtual void onSessionSetupReply (const SessionSetupReply& reply) 55 | { 56 | switch (reply.status) 57 | { 58 | case SessionSetupStatus_Success: 59 | 60 | // Store the session id that will be subsequently used. 61 | currentSessionId = reply.remoteSessionId; 62 | 63 | // Apply the pending setup to the current settings. 64 | lastSessionSetup.applyTo(currentSessionSettings); 65 | 66 | reset(); 67 | 68 | onRemoteSessionSetupSuccess(); 69 | 70 | break; 71 | 72 | case SessionSetupStatus_Failure: 73 | 74 | // FIXME: Call back the server. 75 | // FIXME: Try other setups. 76 | 77 | onRemoteSessionSetupFailure(); 78 | 79 | break; 80 | 81 | default: 82 | break; 83 | } 84 | } 85 | }; 86 | 87 | // FIXME: Remove this once all the dependent code has been updated. 88 | typedef ServerSession ServerSessionBase; 89 | 90 | //------------------------------------------------------------------------------ 91 | 92 | class ServerDelegate 93 | { 94 | protected: 95 | virtual ~ServerDelegate () {} 96 | ServerDelegate () {} 97 | 98 | public: 99 | virtual ServerSession* newSession (int socketDescriptor, Server* server) = 0; 100 | 101 | virtual void onConnect (uintptr_t sessionId) = 0; 102 | virtual void onDisconnect(uintptr_t sessionId) {} 103 | }; 104 | 105 | //------------------------------------------------------------------------------ 106 | 107 | class Server : public ServicePublisher 108 | { 109 | public: 110 | Server (const std::string& serviceName, int servicePort, objc_weak ServerDelegate* serverDelegate); 111 | 112 | virtual ~Server (); 113 | 114 | public: 115 | bool startListening (const char* ipAddress = 0); 116 | 117 | void onConnect (int socketDescriptor); 118 | void onDisconnect (int socketDescriptor, ServerSession* session); 119 | 120 | protected: 121 | void clear(); 122 | 123 | private: 124 | class ConnectionListener; 125 | 126 | private: 127 | ConnectionListener* _listener; 128 | int _port; 129 | std::vector _sessions; 130 | ServerDelegate* _serverDelegate; 131 | 132 | public: 133 | ServerSession* _currentSession; 134 | 135 | public: 136 | void* userdata; 137 | }; 138 | 139 | //------------------------------------------------------------------------------ 140 | 141 | } 142 | 143 | # include "./servers.hpp" 144 | -------------------------------------------------------------------------------- /headers/services.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./core/datagrams.h" 8 | # include "./core/threads.h" 9 | # include 10 | # include 11 | 12 | namespace uplink { 13 | 14 | //------------------------------------------------------------------------------ 15 | 16 | struct VersionInfo : Message 17 | { 18 | UPLINK_MESSAGE_CLASS(VersionInfo) 19 | 20 | VersionInfo () 21 | : major(0) 22 | , minor(0) 23 | { 24 | 25 | } 26 | 27 | VersionInfo (uint8 major, uint8 minor) 28 | : major(major), minor(minor) 29 | { 30 | 31 | } 32 | 33 | virtual bool serializeWith (Serializer& s) 34 | { 35 | return_false_unless(s.put(major)); 36 | return_false_unless(s.put(minor)); 37 | 38 | return true; 39 | } 40 | 41 | bool isValid () const 42 | { 43 | return major != 0 || minor != 0; 44 | } 45 | 46 | bool operator == (const VersionInfo& rhs) const 47 | { 48 | return major == rhs.major && minor == rhs.minor; 49 | } 50 | 51 | bool operator < (const VersionInfo& rhs) const 52 | { 53 | return major == rhs.major 54 | ? minor < rhs.minor 55 | : major < rhs.major 56 | ; 57 | } 58 | 59 | bool operator <= (const VersionInfo& rhs) const 60 | { 61 | return *this < rhs || *this == rhs; 62 | } 63 | 64 | void swapWith (VersionInfo& other) 65 | { 66 | Message::swapWith(other); 67 | 68 | uplink_swap(major, other.major); 69 | uplink_swap(minor, other.minor); 70 | } 71 | 72 | uint8 major; 73 | uint8 minor; 74 | }; 75 | 76 | struct VersionRange 77 | { 78 | VersionRange () 79 | : minimum() 80 | , maximum() 81 | { 82 | 83 | } 84 | 85 | VersionRange ( 86 | const uint8 minimum_major, const uint8 minimum_minor, 87 | const uint8 maximum_major, const uint8 maximum_minor 88 | ) 89 | : minimum(minimum_major, minimum_minor) 90 | , maximum(maximum_major, maximum_minor) 91 | { 92 | 93 | } 94 | 95 | bool isValid () const 96 | { 97 | return minimum.isValid() && maximum.isValid(); 98 | } 99 | 100 | enum Compatibility 101 | { 102 | VersionIsOlder, 103 | VersionIsCompatible, 104 | VersionIsNewer 105 | }; 106 | 107 | Compatibility compatibilityWith (const VersionInfo& versionInfo) const 108 | { 109 | if (versionInfo < minimum) 110 | return VersionIsOlder; 111 | else if (maximum < versionInfo) 112 | return VersionIsNewer; 113 | else 114 | return VersionIsCompatible; 115 | } 116 | 117 | VersionInfo minimum; 118 | VersionInfo maximum; 119 | }; 120 | 121 | //------------------------------------------------------------------------------ 122 | 123 | struct ServiceEntry 124 | { 125 | //FIXME: This should be removed. Passing an improperly initialized ServiceEntry around will cause bad access errors 126 | ServiceEntry () 127 | {} 128 | 129 | ServiceEntry (const String& serviceName, uint16 port, const VersionRange& versionRange) 130 | : serviceName(serviceName) 131 | , port(port) 132 | , versionRange(versionRange) 133 | { 134 | } 135 | 136 | String serviceName; 137 | uint16 port; 138 | VersionRange versionRange; 139 | }; 140 | 141 | //------------------------------------------------------------------------------ 142 | 143 | struct Service 144 | { 145 | //FIXME: This should be removed. Passing an improperly initialized Services around will cause bad access errors 146 | Service () 147 | {} 148 | 149 | Service (const ServiceEntry &entry, const NetworkAddress& address) 150 | : entry(entry) 151 | , address(address) 152 | { 153 | } 154 | 155 | VersionRange::Compatibility compatibilityWith (const VersionInfo& versionInfo) const 156 | { 157 | return entry.versionRange.compatibilityWith(versionInfo); 158 | } 159 | 160 | VersionRange::Compatibility compatibilityWithClientVersion () const; 161 | 162 | ServiceEntry entry; 163 | NetworkAddress address; 164 | }; 165 | 166 | //------------------------------------------------------------------------------ 167 | 168 | inline const VersionRange& 169 | serverVersionRange () 170 | { 171 | static const VersionRange instance = VersionRange( 172 | UPLINK_SERVER_MINIMUM_VERSION_MAJOR, 173 | UPLINK_SERVER_MINIMUM_VERSION_MINOR, 174 | UPLINK_SERVER_MAXIMUM_VERSION_MAJOR, 175 | UPLINK_SERVER_MAXIMUM_VERSION_MINOR 176 | ); 177 | 178 | return instance; 179 | } 180 | 181 | inline const VersionInfo& 182 | clientVersion () 183 | { 184 | static const VersionInfo instance = VersionInfo( 185 | UPLINK_CLIENT_VERSION_MAJOR, 186 | UPLINK_CLIENT_VERSION_MINOR 187 | ); 188 | 189 | return instance; 190 | } 191 | 192 | inline 193 | VersionRange::Compatibility 194 | Service::compatibilityWithClientVersion () const 195 | { 196 | return compatibilityWith(clientVersion()); 197 | } 198 | 199 | } 200 | 201 | # include "./services.hpp" 202 | -------------------------------------------------------------------------------- /headers/services.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./services.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | } 16 | -------------------------------------------------------------------------------- /headers/sessions-settings.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./sessions-settings.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | inline 14 | SessionSettings::SessionSettings () 15 | { 16 | // Default to the minimum. 17 | 18 | depthMode = DepthMode_None; 19 | 20 | colorMode = ColorMode_None; 21 | 22 | infraredMode = InfraredMode_None; 23 | 24 | registrationMode = RegistrationMode_None; 25 | 26 | frameSyncMode = FrameSyncMode_None; 27 | 28 | sporadicFrameColor = false; 29 | sporadicFrameColorDivisor = 1; 30 | 31 | sendMotion = false; 32 | motionRate = 50; 33 | 34 | lockColorCameraGainOnRecord = false; 35 | 36 | colorCameraExposureMode = ColorCameraExposureMode_ContinuousAuto; 37 | colorCameraWhiteBalanceMode = ColorCameraWhiteBalanceMode_ContinuousAuto; 38 | 39 | // Reset to safe defaults. Wrong image formats have happened and will happen again, otherwise. 40 | depthCameraCodec = ImageCodecId_Invalid; 41 | colorCameraCodec = ImageCodecId_Invalid; 42 | feedbackImageCodec = ImageCodecId_Invalid; 43 | 44 | // Channel settings are initialized in their default-constructor. 45 | } 46 | 47 | inline void 48 | SessionSettings::clear () 49 | { 50 | *this = SessionSettings(); 51 | } 52 | 53 | inline bool 54 | SessionSettings::serializeWith (Serializer& serializer) 55 | { 56 | # define UPLINK_SESSION_SETTING(Type, Name, name) \ 57 | return_false_unless(serializer.put(name)); 58 | UPLINK_SESSION_SETTINGS() 59 | # undef UPLINK_SESSION_SETTING 60 | 61 | return true; 62 | } 63 | 64 | //------------------------------------------------------------------------------ 65 | 66 | } 67 | -------------------------------------------------------------------------------- /headers/sessions-setup-presets.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./sessions-setup.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | struct SporadicColorSessionSetup : SessionSetup 14 | { 15 | SporadicColorSessionSetup() 16 | { 17 | addSetColorModeAction(ColorMode_VGA); 18 | addSetDepthModeAction(DepthMode_VGA); 19 | addSetRegistrationModeAction(RegistrationMode_RegisteredDepth); 20 | addSetFrameSyncModeAction(FrameSyncMode_Depth); 21 | 22 | addSetSporadicFrameColorAction(true); 23 | addSetSporadicFrameColorDivisorAction(6); 24 | 25 | ChannelSettings channelSettings; 26 | channelSettings.droppingStrategy = DroppingStrategy_RandomOne; 27 | channelSettings.droppingThreshold = 90; 28 | channelSettings.bufferingStrategy = BufferingStrategy_Some; 29 | 30 | addSetRGBDFrameChannelAction(channelSettings); 31 | 32 | addSetSendMotionAction(false); 33 | addSetMotionRateAction(100); 34 | 35 | addSetColorCameraExposureModeAction(ColorCameraExposureMode_ContinuousAuto); 36 | addSetColorCameraWhiteBalanceModeAction(ColorCameraWhiteBalanceMode_ContinuousAuto); 37 | } 38 | }; 39 | 40 | //------------------------------------------------------------------------------ 41 | 42 | struct Depth60FPSSessionSetup : SessionSetup 43 | { 44 | Depth60FPSSessionSetup() 45 | { 46 | addSetColorModeAction(ColorMode_None); 47 | addSetDepthModeAction(DepthMode_QVGA_60FPS); 48 | addSetRegistrationModeAction(RegistrationMode_None); 49 | addSetFrameSyncModeAction(FrameSyncMode_None); 50 | 51 | addSetSporadicFrameColorAction(false); 52 | addSetSporadicFrameColorDivisorAction(6); 53 | 54 | ChannelSettings channelSettings; 55 | channelSettings.droppingStrategy = DroppingStrategy_RandomOne; 56 | channelSettings.droppingThreshold = 90; 57 | channelSettings.bufferingStrategy = BufferingStrategy_Some; 58 | 59 | addSetRGBDFrameChannelAction(channelSettings); 60 | 61 | addSetSendMotionAction(false); 62 | addSetMotionRateAction(100); 63 | 64 | addSetColorCameraExposureModeAction(ColorCameraExposureMode_ContinuousAuto); 65 | addSetColorCameraWhiteBalanceModeAction(ColorCameraWhiteBalanceMode_ContinuousAuto); 66 | } 67 | }; 68 | 69 | //------------------------------------------------------------------------------ 70 | 71 | struct WXGASessionSetup : SessionSetup 72 | { 73 | WXGASessionSetup() 74 | { 75 | addSetColorModeAction(ColorMode_1296x968); 76 | addSetDepthModeAction(DepthMode_VGA); 77 | addSetRegistrationModeAction(RegistrationMode_RegisteredDepth); 78 | addSetFrameSyncModeAction(FrameSyncMode_Depth); 79 | 80 | addSetSporadicFrameColorAction(false); 81 | addSetSporadicFrameColorDivisorAction(6); 82 | 83 | ChannelSettings channelSettings; 84 | channelSettings.droppingStrategy = DroppingStrategy_RandomOne; 85 | channelSettings.droppingThreshold = 90; 86 | channelSettings.bufferingStrategy = BufferingStrategy_Some; 87 | 88 | addSetRGBDFrameChannelAction(channelSettings); 89 | 90 | addSetSendMotionAction(false); 91 | addSetMotionRateAction(100); 92 | 93 | addSetColorCameraExposureModeAction(ColorCameraExposureMode_ContinuousAuto); 94 | addSetColorCameraWhiteBalanceModeAction(ColorCameraWhiteBalanceMode_ContinuousAuto); 95 | } 96 | }; 97 | 98 | //------------------------------------------------------------------------------ 99 | 100 | } 101 | 102 | # include "./sessions-setup-presets.hpp" 103 | -------------------------------------------------------------------------------- /headers/sessions-setup-presets.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./sessions-setup-presets.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | //------------------------------------------------------------------------------ 14 | 15 | } 16 | -------------------------------------------------------------------------------- /headers/sessions-setup.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./sessions-settings.h" 8 | # include "./core/serializers.h" 9 | # include "./core/enum.h" 10 | # include 11 | 12 | namespace uplink { 13 | 14 | //------------------------------------------------------------------------------ 15 | 16 | struct SessionSetupAction : Serializable, Clonable 17 | { 18 | virtual bool applyTo (SessionSettings& sessionSettings) const = 0; 19 | }; 20 | 21 | typedef uplink_ref SessionSetupActionRef; 22 | 23 | //------------------------------------------------------------------------------ 24 | 25 | UPLINK_ENUM_BEGIN(SessionSetupActionKind) 26 | # define UPLINK_SESSION_SETTING(Type, Name, name) \ 27 | SessionSetupActionKind_Set##Name, 28 | UPLINK_SESSION_SETTINGS() 29 | # undef UPLINK_SESSION_SETTING 30 | UPLINK_ENUM_END(SessionSetupActionKind) 31 | 32 | static SessionSetupAction* newSessionSetupAction (SessionSetupActionKind kind); 33 | 34 | //------------------------------------------------------------------------------ 35 | 36 | # define UPLINK_SESSION_SETTING(Type, Name, name) \ 37 | struct Set##Name##SessionSetupAction : SessionSetupAction \ 38 | { \ 39 | Set##Name##SessionSetupAction () {} \ 40 | Set##Name##SessionSetupAction (const Type& value) : value(value) {} \ 41 | Set##Name##SessionSetupAction (const Set##Name##SessionSetupAction& copy) : value(copy.value) {} \ 42 | virtual SessionSetupAction* clone () const { return new Set##Name##SessionSetupAction(*this); } \ 43 | virtual bool applyTo (SessionSettings& sessionSettings) const { sessionSettings.set##Name(value); return true; } \ 44 | virtual bool serializeWith (Serializer& serializer) { return serializer.put(value); } \ 45 | Type value; \ 46 | }; 47 | UPLINK_SESSION_SETTINGS() 48 | # undef UPLINK_SESSION_SETTING 49 | 50 | //------------------------------------------------------------------------------ 51 | 52 | struct AnySessionSetupAction : SessionSetupAction 53 | { 54 | AnySessionSetupAction (); 55 | AnySessionSetupAction (const AnySessionSetupAction& copy); 56 | 57 | void swapWith (AnySessionSetupAction& other); 58 | 59 | void clear (); 60 | 61 | # define UPLINK_SESSION_SETTING(Type, Name, name) \ 62 | void resetAsSet##Name (const Type& value) \ 63 | { \ 64 | kind = SessionSetupActionKind_Set##Name; \ 65 | that.reset(new Set##Name##SessionSetupAction(value)); \ 66 | } 67 | UPLINK_SESSION_SETTINGS() 68 | # undef UPLINK_SESSION_SETTING 69 | 70 | virtual SessionSetupAction* clone () const { return new AnySessionSetupAction(*this); } 71 | 72 | virtual bool serializeWith (Serializer& serializer); 73 | 74 | virtual bool applyTo (SessionSettings& sessionSettings) const; 75 | 76 | SessionSetupActionKind kind; 77 | SessionSetupActionRef that; 78 | }; 79 | 80 | //------------------------------------------------------------------------------ 81 | 82 | struct SessionSetup : SessionSetupAction, Message 83 | { 84 | UPLINK_MESSAGE_CLASS(SessionSetup) 85 | 86 | static const SessionSetup& defaults (); 87 | 88 | SessionSetup (); 89 | 90 | void swapWith (SessionSetup& other); 91 | 92 | virtual bool serializeWith (Serializer &serializer); 93 | 94 | virtual bool applyTo (SessionSettings& sessionSettings) const; 95 | 96 | # define UPLINK_SESSION_SETTING(Type, Name, name) \ 97 | void addSet##Name##Action (const Type& value) \ 98 | { \ 99 | actions.push_back(AnySessionSetupAction()); \ 100 | actions.back().resetAsSet##Name(value); \ 101 | } 102 | UPLINK_SESSION_SETTINGS() 103 | # undef UPLINK_SESSION_SETTING 104 | 105 | std::vector actions; 106 | }; 107 | 108 | //------------------------------------------------------------------------------ 109 | 110 | } 111 | 112 | # include "./sessions-setup.hpp" 113 | -------------------------------------------------------------------------------- /headers/sessions-setup.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "./sessions-setup.h" 8 | 9 | namespace uplink { 10 | 11 | //------------------------------------------------------------------------------ 12 | 13 | inline 14 | AnySessionSetupAction:: 15 | AnySessionSetupAction () 16 | : kind(SessionSetupActionKind_Invalid) 17 | { 18 | 19 | } 20 | 21 | inline 22 | AnySessionSetupAction:: 23 | AnySessionSetupAction (const AnySessionSetupAction& copy) 24 | : kind(copy.kind) 25 | , that(copy.kind == SessionSetupActionKind_Invalid ? 0 : copy.that->clone()) 26 | {} 27 | 28 | inline void 29 | AnySessionSetupAction:: 30 | swapWith (AnySessionSetupAction& other) 31 | { 32 | uplink_swap(kind, other.kind); 33 | uplink_swap(that, other.that); 34 | } 35 | 36 | inline void 37 | AnySessionSetupAction:: 38 | clear () 39 | { 40 | kind = SessionSetupActionKind_Invalid; 41 | that.reset(); 42 | } 43 | 44 | inline bool 45 | AnySessionSetupAction:: 46 | serializeWith (Serializer& serializer) 47 | { 48 | if (serializer.isReader()) 49 | { 50 | that.reset(); 51 | return_false_unless(serializer.asReader().read(kind)); 52 | return_false_if(SessionSetupActionKind_Invalid == kind); // Reading an invalid action doesn't make sense. 53 | that.reset(newSessionSetupAction(kind)); 54 | } 55 | else 56 | { 57 | return_false_if(SessionSetupActionKind_Invalid == kind); // Writing an invalid action doesn't make sense. 58 | return_false_unless(serializer.asWriter().write(kind)); 59 | } 60 | 61 | return serializer.put(*that); 62 | } 63 | 64 | inline bool 65 | AnySessionSetupAction:: 66 | applyTo (SessionSettings& sessionSettings) const 67 | { 68 | return_false_if(!that); // An invalid action cannot be executed. 69 | 70 | return that->applyTo(sessionSettings); 71 | } 72 | 73 | //------------------------------------------------------------------------------ 74 | 75 | inline 76 | SessionSetup:: 77 | SessionSetup () 78 | { 79 | // Start with an empty action list. 80 | } 81 | 82 | inline void 83 | SessionSetup:: 84 | swapWith (SessionSetup& other) 85 | { 86 | Message::swapWith(other); 87 | 88 | uplink_swap(actions, other.actions); 89 | } 90 | 91 | inline bool 92 | SessionSetup:: 93 | serializeWith (Serializer &serializer) 94 | { 95 | if(serializer.isReader()) 96 | { 97 | uint16 size; 98 | return_false_unless(serializer.asReader().read(size)); 99 | // FIXME: Maximum size check. 100 | actions.resize(size); 101 | } 102 | else 103 | { 104 | return_false_unless(serializer.asWriter().write(uint16(actions.size()))); 105 | } 106 | 107 | for (int n = 0; n < actions.size(); ++n) 108 | return_false_unless(actions[n].serializeWith(serializer)); 109 | 110 | return true; 111 | } 112 | 113 | inline bool 114 | SessionSetup:: 115 | applyTo (SessionSettings& sessionSettings) const 116 | { 117 | for (int n = 0; n < actions.size(); ++n) 118 | return_false_unless(actions[n].applyTo(sessionSettings)); 119 | 120 | return true; 121 | } 122 | 123 | inline SessionSetupAction* 124 | newSessionSetupAction (SessionSetupActionKind kind) 125 | { 126 | switch (kind.value) 127 | { 128 | # define UPLINK_SESSION_SETTING(Type, Name, name) \ 129 | case SessionSetupActionKind_Set##Name: \ 130 | return new Set##Name##SessionSetupAction(); 131 | UPLINK_SESSION_SETTINGS() 132 | # undef UPLINK_SESSION_SETTING 133 | 134 | default: 135 | return 0; 136 | } 137 | } 138 | 139 | inline const SessionSetup& 140 | SessionSetup:: 141 | defaults () 142 | { 143 | static SessionSetup cfg; 144 | 145 | static bool initialized = false; 146 | 147 | if(initialized) 148 | return cfg; 149 | 150 | initialized = true; 151 | 152 | static const SessionSettings defaultSettings; 153 | 154 | # define UPLINK_SESSION_SETTING(Type, Name, name) \ 155 | { \ 156 | cfg.actions.push_back(AnySessionSetupAction()); \ 157 | cfg.actions.back().resetAs##Set##Name(defaultSettings.name); \ 158 | } 159 | UPLINK_SESSION_SETTINGS() 160 | # undef UPLINK_SESSION_SETTING 161 | 162 | return cfg; 163 | } 164 | 165 | //------------------------------------------------------------------------------ 166 | 167 | } 168 | -------------------------------------------------------------------------------- /headers/shift-depth-converter.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include 8 | # include 9 | 10 | namespace uplink { 11 | 12 | struct ShiftDepthConverter 13 | { 14 | public: 15 | void initialize ( 16 | float cmosAndEmitterDistance, 17 | float referencePlaneDistance, 18 | float planePixelSize, 19 | int sensorPixelSizeFactor, 20 | float registeredDepthOffset 21 | ); 22 | 23 | void initializeWithDefaults (); 24 | 25 | public: 26 | bool isValid () const; 27 | 28 | public: 29 | float shiftToDepthInMillimeters (float shift); 30 | float depthInMillimetersToShift (float depthInMillimeters); 31 | 32 | private: 33 | float cmosAndEmitterDistance = NAN; 34 | float referencePlaneDistance = NAN; 35 | float planePixelSize = NAN; 36 | double fRegisteredDepthOffset = NAN; 37 | int sensorPixelSizeFactor = -1; 38 | 39 | private: 40 | double A = NAN; 41 | double B = NAN; 42 | }; 43 | 44 | } // uplink namespace 45 | 46 | # include "shift-depth-converter.hpp" 47 | -------------------------------------------------------------------------------- /headers/shift-depth-converter.hpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | # include "shift-depth-converter.h" 8 | 9 | # include 10 | 11 | namespace uplink { 12 | 13 | inline void 14 | ShiftDepthConverter::initialize ( 15 | float cmosAndEmitterDistance, 16 | float referencePlaneDistance, 17 | float planePixelSize, 18 | int sensorPixelSizeFactor, 19 | float registeredDepthOffset 20 | ) 21 | { 22 | // Save input parameters. 23 | this->cmosAndEmitterDistance = cmosAndEmitterDistance; 24 | this->referencePlaneDistance = referencePlaneDistance; 25 | this->planePixelSize = planePixelSize; 26 | this->fRegisteredDepthOffset = registeredDepthOffset; 27 | this->sensorPixelSizeFactor = sensorPixelSizeFactor; 28 | 29 | assert(!isnan(cmosAndEmitterDistance)); 30 | assert(!isnan(referencePlaneDistance)); 31 | assert(!isnan(planePixelSize)); 32 | assert(sensorPixelSizeFactor > 0); 33 | 34 | double nZeroPlaneDistance = referencePlaneDistance; // As measured to camera pupil. 35 | double fEmitterDCmosDistance = cmosAndEmitterDistance; 36 | 37 | const int nPixelSizeFactor = sensorPixelSizeFactor; 38 | const int nShiftScale= 10; 39 | const int nParamCoeff= 4; 40 | const int nConstShiftWithoutParamCoeff = 200; 41 | 42 | const double dPlanePixelSize = planePixelSize * nPixelSizeFactor; 43 | const double dPlaneDsr = nZeroPlaneDistance; 44 | const double dPlaneDcl = fEmitterDCmosDistance; 45 | 46 | double nConstShift = double(nParamCoeff * nConstShiftWithoutParamCoeff) / nPixelSizeFactor; 47 | 48 | // Matlab code to recover the expressions below: 49 | // 50 | // syms X nConstShift nParamCoeff dPlanePixelSize nShiftScale dPlaneDsr dPlaneDcl dPlaneDsr 51 | // collect(nShiftScale * ((((dPlanePixelSize*(((X - nConstShift)/nParamCoeff) - 0.375)) * dPlaneDsr) / (dPlaneDcl - (dPlanePixelSize * (((X - nConstShift) / nParamCoeff) - 0.375)))) + dPlaneDsr), X) 52 | // 53 | // Then manual simplification. 54 | 55 | this->A = (-8 * dPlaneDcl * dPlaneDsr * nParamCoeff * nShiftScale) / (8 * dPlanePixelSize); 56 | this->B = (-8 * dPlanePixelSize * nConstShift - 8 * dPlaneDcl * nParamCoeff - 3 * dPlanePixelSize * nParamCoeff) / (8 * dPlanePixelSize); 57 | } 58 | 59 | inline void 60 | ShiftDepthConverter::initializeWithDefaults () 61 | { 62 | static const float cmosAndEmitterDistance = 6.5f; // CMOS and emitter distance value is in centimeters and fixed for all Structure Sensors. 63 | static const float referencePlaneDistance = 90.0f; // Reference plane distance value is in centimeters and fixed for all Structure Sensors. 64 | static const float planePixelSize = 0.078f; // Plane pixel size is normally a sensor-specific, factory-calibrated. Using an approximation here. 65 | static const int sensorPixelSizeFactor = 1; 66 | static const float registeredDepthOffset = 0.f; 67 | 68 | initialize(cmosAndEmitterDistance, referencePlaneDistance, planePixelSize, sensorPixelSizeFactor, registeredDepthOffset); 69 | } 70 | 71 | inline bool 72 | ShiftDepthConverter::isValid () const 73 | { 74 | return !isnan(A) && !isnan(B); 75 | } 76 | 77 | inline float 78 | ShiftDepthConverter::shiftToDepthInMillimeters (float shift) 79 | { 80 | assert(isValid()); 81 | 82 | return (A / (shift + B)) + fRegisteredDepthOffset; 83 | } 84 | 85 | inline float 86 | ShiftDepthConverter::depthInMillimetersToShift (float depthInMillimeters) 87 | { 88 | assert(isValid()); 89 | 90 | return -B + 1.0 / ((depthInMillimeters - fRegisteredDepthOffset) / A); 91 | } 92 | 93 | } // uplink namespace 94 | -------------------------------------------------------------------------------- /headers/uplink.h: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | # pragma once 6 | 7 | //------------------------------------------------------------------------------ 8 | 9 | // Uplink 1.2 10 | 11 | # define UPLINK_SERVER_MINIMUM_VERSION_MAJOR 1 12 | # define UPLINK_SERVER_MINIMUM_VERSION_MINOR 2 13 | # define UPLINK_SERVER_MAXIMUM_VERSION_MAJOR 1 14 | # define UPLINK_SERVER_MAXIMUM_VERSION_MINOR 2 15 | 16 | # define UPLINK_CLIENT_VERSION_MAJOR 1 17 | # define UPLINK_CLIENT_VERSION_MINOR 2 18 | 19 | //------------------------------------------------------------------------------ 20 | 21 | # include "./core/platform.h" 22 | 23 | //------------------------------------------------------------------------------ 24 | 25 | # include "./context.h" 26 | # include "./clients.h" 27 | # include "./image.h" 28 | # include "./image-codecs.h" 29 | # include "./camera-calibration.h" 30 | # include "./camera-fixedparams.h" 31 | # include "./camera-pose.h" 32 | # include "./camera-frame.h" 33 | # include "./endpoints.h" 34 | # include "./discovery.h" 35 | # include "./messages.h" 36 | # include "./motion.h" 37 | # include "./servers.h" 38 | # include "./desktop-server.h" 39 | # include "./services.h" 40 | # include "./sessions-settings.h" 41 | # include "./sessions-setup.h" 42 | # include "./sessions-setup-presets.h" 43 | # include "./shift-depth-converter.h" 44 | 45 | //------------------------------------------------------------------------------ 46 | 47 | // OSX's AssertMacros.h header defines the 'check' macro, which other headers (ie: Qt) may not like. 48 | # ifdef check 49 | # undef check 50 | # endif 51 | -------------------------------------------------------------------------------- /projects/uplink-vs2012-example-server.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8} 21 | Win32Proj 22 | uplinkserver 23 | example-server 24 | 25 | 26 | 27 | Application 28 | true 29 | v110 30 | MultiByte 31 | 32 | 33 | Application 34 | false 35 | v110 36 | true 37 | MultiByte 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | true 51 | $(ProjectDir)..\builds\vs2012-$(ProjectName)\$(Configuration)\ 52 | $(ProjectDir)..\builds\vs2012-$(ProjectName)\$(Configuration)\ 53 | 54 | 55 | false 56 | $(ProjectDir)..\builds\vs2012-$(ProjectName)\$(Configuration)\ 57 | $(ProjectDir)..\builds\vs2012-$(ProjectName)\$(Configuration)\ 58 | 59 | 60 | 61 | 62 | 63 | Level3 64 | Disabled 65 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 66 | $(ProjectDir)..\headers;$(ProjectDir)..\dependencies\headers;$(ProjectDir)..\sources;%(AdditionalIncludeDirectories) 67 | false 68 | 69 | 70 | Console 71 | true 72 | Gdiplus.lib;Shlwapi.lib;glfw3.lib;opengl32.lib;%(AdditionalDependencies) 73 | $(ProjectDir)..\dependencies\binaries\win64;%(AdditionalLibraryDirectories) 74 | 75 | 76 | copy $(ProjectDir)\..\examples\*.png $(OutDir) 77 | 78 | 79 | Copying PNG example resources... 80 | 81 | 82 | 83 | 84 | Level3 85 | 86 | 87 | MaxSpeed 88 | true 89 | true 90 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | $(ProjectDir)..\headers;$(ProjectDir)..\dependencies\headers;$(ProjectDir)..\sources;%(AdditionalIncludeDirectories) 92 | false 93 | 94 | 95 | Console 96 | true 97 | true 98 | Gdiplus.lib;Shlwapi.lib;glfw3.lib;opengl32.lib;%(AdditionalDependencies) 99 | $(ProjectDir)..\dependencies\binaries\win64;%(AdditionalLibraryDirectories) 100 | 101 | 102 | 103 | 104 | 105 | copy $(ProjectDir)\..\examples\*.png $(OutDir) 106 | 107 | 108 | Copying PNG example resources... 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /projects/uplink-vs2012.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uplink-vs2012-example-server", "uplink-vs2012-example-server.vcxproj", "{5BB76BC3-A287-4BC9-9E4F-7801001493D8}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x64 = Debug|x64 9 | Release|x64 = Release|x64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8}.Debug|x64.ActiveCfg = Debug|x64 13 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8}.Debug|x64.Build.0 = Debug|x64 14 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8}.Release|x64.ActiveCfg = Release|x64 15 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8}.Release|x64.Build.0 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /projects/uplink-vs2013-example-server.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8} 21 | Win32Proj 22 | uplinkserver 23 | example-server 24 | 25 | 26 | 27 | Application 28 | true 29 | v120 30 | MultiByte 31 | 32 | 33 | Application 34 | false 35 | v120 36 | true 37 | MultiByte 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | true 51 | $(ProjectDir)..\builds\vs2013-$(ProjectName)\$(Configuration)\ 52 | $(ProjectDir)..\builds\vs2013-$(ProjectName)\$(Configuration)\ 53 | 54 | 55 | false 56 | $(ProjectDir)..\builds\vs2013-$(ProjectName)\$(Configuration)\ 57 | $(ProjectDir)..\builds\vs2013-$(ProjectName)\$(Configuration)\ 58 | 59 | 60 | 61 | 62 | 63 | Level3 64 | Disabled 65 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 66 | $(ProjectDir)..\headers;$(ProjectDir)..\dependencies\headers;$(ProjectDir)..\sources;%(AdditionalIncludeDirectories) 67 | false 68 | 69 | 70 | Console 71 | true 72 | Gdiplus.lib;Shlwapi.lib;glfw3.lib;opengl32.lib;%(AdditionalDependencies) 73 | $(ProjectDir)..\dependencies\binaries\win64;%(AdditionalLibraryDirectories) 74 | 75 | 76 | copy $(ProjectDir)\..\examples\*.png $(OutDir) 77 | 78 | 79 | Copying PNG example resources... 80 | 81 | 82 | 83 | 84 | Level3 85 | 86 | 87 | MaxSpeed 88 | true 89 | true 90 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | $(ProjectDir)..\headers;$(ProjectDir)..\dependencies\headers;$(ProjectDir)..\sources;%(AdditionalIncludeDirectories) 92 | false 93 | 94 | 95 | Console 96 | true 97 | true 98 | Gdiplus.lib;Shlwapi.lib;glfw3.lib;opengl32.lib;%(AdditionalDependencies) 99 | $(ProjectDir)..\dependencies\binaries\win64;%(AdditionalLibraryDirectories) 100 | 101 | 102 | 103 | 104 | 105 | copy $(ProjectDir)\..\examples\*.png $(OutDir) 106 | 107 | 108 | Copying PNG example resources... 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /projects/uplink-vs2013.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uplink-vs2013-example-server", "uplink-vs2013-example-server.vcxproj", "{5BB76BC3-A287-4BC9-9E4F-7801001493D8}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8}.Debug|x64.ActiveCfg = Debug|x64 15 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8}.Debug|x64.Build.0 = Debug|x64 16 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8}.Release|x64.ActiveCfg = Release|x64 17 | {5BB76BC3-A287-4BC9-9E4F-7801001493D8}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /scripts/build-cmake-make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | HERE=`cd "\`dirname \"$0\"\`";pwd` 3 | 4 | CMAKE_GENERATOR="Unix Makefiles" 5 | CMAKE_BUILD_TYPE=Release 6 | UPLINK_DIR="$HERE/.." 7 | BUILD_DIR="$UPLINK_DIR"/builds/cmake-make-r 8 | 9 | mkdir -p "$BUILD_DIR" 10 | pushd "$BUILD_DIR" 11 | cmake \ 12 | -DCMAKE_BUILD_TYPE:STRING=$CMAKE_BUILD_TYPE \ 13 | -G"$CMAKE_GENERATOR" \ 14 | "$UPLINK_DIR" 15 | 16 | make 17 | popd 18 | -------------------------------------------------------------------------------- /scripts/build-cmake-nmake.cmd: -------------------------------------------------------------------------------- 1 | set UPLINK_DIR="%~dp0\.." 2 | set BUILD_DIR="%~dp0\..\builds\cmake-nmake-r" 3 | set CMAKE_GENERATOR="NMake Makefiles" 4 | set CMAKE_BUILD_TYPE=Release 5 | mkdir %BUILD_DIR% 6 | pushd %BUILD_DIR% 7 | if %ERRORLEVEL% equ 0 call cmake -DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE% -G%CMAKE_GENERATOR% %UPLINK_DIR% 8 | if %ERRORLEVEL% equ 0 call nmake 9 | popd 10 | -------------------------------------------------------------------------------- /scripts/build-cmake-vs2012.cmd: -------------------------------------------------------------------------------- 1 | set UPLINK_DIR="%~dp0\.." 2 | set BUILD_DIR="%~dp0\..\builds\cmake-win64-vs2012" 3 | set CMAKE_GENERATOR="Visual Studio 11 Win64" 4 | set CMAKE_BUILD_TYPES="Release;Debug" 5 | mkdir %BUILD_DIR% 6 | pushd %BUILD_DIR% 7 | if %ERRORLEVEL% equ 0 call cmake -G%CMAKE_GENERATOR% -DCMAKE_CONFIGURATION_TYPES=%CMAKE_BUILD_TYPES% %UPLINK_DIR% 8 | if %ERRORLEVEL% equ 0 call "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\Common7\Ide\devenv.exe" uplink.sln 9 | popd 10 | -------------------------------------------------------------------------------- /scripts/build-cmake-vs2013.cmd: -------------------------------------------------------------------------------- 1 | set UPLINK_DIR="%~dp0\.." 2 | set BUILD_DIR="%~dp0\..\builds\cmake-win64-vs2013" 3 | set CMAKE_GENERATOR="Visual Studio 12 Win64" 4 | set CMAKE_BUILD_TYPES="Release;Debug" 5 | mkdir %BUILD_DIR% 6 | pushd %BUILD_DIR% 7 | if %ERRORLEVEL% equ 0 call cmake -G%CMAKE_GENERATOR% -DCMAKE_CONFIGURATION_TYPES=%CMAKE_BUILD_TYPES% %UPLINK_DIR% 8 | if %ERRORLEVEL% equ 0 call "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\Common7\Ide\devenv.exe" uplink.sln 9 | popd 10 | -------------------------------------------------------------------------------- /scripts/build-cmake-xcode.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | HERE=`cd "\`dirname \"$0\"\`";pwd` 3 | 4 | CMAKE_GENERATOR="Xcode" 5 | CMAKE_BUILD_TYPES="Release;Debug" 6 | UPLINK_DIR="$HERE/.." 7 | BUILD_DIR="$UPLINK_DIR"/builds/cmake-xcode 8 | 9 | mkdir -p "$BUILD_DIR" 10 | pushd "$BUILD_DIR" 11 | cmake \ 12 | -DCMAKE_BUILD_TYPE:STRING=$CMAKE_BUILD_TYPE \ 13 | -DCMAKE_CONFIGURATION_TYPES:STRING="$CMAKE_BUILD_TYPES" \ 14 | -G"$CMAKE_GENERATOR" \ 15 | "$UPLINK_DIR" 16 | 17 | open uplink.xcodeproj 18 | popd 19 | -------------------------------------------------------------------------------- /sources/uplink.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | #include "../headers/uplink.h" 6 | 7 | namespace uplink { 8 | 9 | Context context; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /sources/uplink.mm: -------------------------------------------------------------------------------- 1 | // This file is part of Uplink, an easy-to-use cross-platform live RGBD streaming protocol. 2 | // Copyright (c) 2016, Occipital, Inc. All rights reserved. 3 | // License: See LICENSE. 4 | 5 | #include "./uplink.cpp" 6 | --------------------------------------------------------------------------------