OpenNI 2.0
OpenNI.h
Go to the documentation of this file.
00001 /*****************************************************************************
00002 *                                                                            *
00003 *  OpenNI 2.x Alpha                                                          *
00004 *  Copyright (C) 2012 PrimeSense Ltd.                                        *
00005 *                                                                            *
00006 *  This file is part of OpenNI.                                              *
00007 *                                                                            *
00008 *  Licensed under the Apache License, Version 2.0 (the "License");           *
00009 *  you may not use this file except in compliance with the License.          *
00010 *  You may obtain a copy of the License at                                   *
00011 *                                                                            *
00012 *      http://www.apache.org/licenses/LICENSE-2.0                            *
00013 *                                                                            *
00014 *  Unless required by applicable law or agreed to in writing, software       *
00015 *  distributed under the License is distributed on an "AS IS" BASIS,         *
00016 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
00017 *  See the License for the specific language governing permissions and       *
00018 *  limitations under the License.                                            *
00019 *                                                                            *
00020 *****************************************************************************/
00021 #ifndef _OPENNI_H_
00022 #define _OPENNI_H_
00023 
00024 #include "OniPlatform.h"
00025 #include "OniProperties.h"
00026 #include "OniEnums.h"
00027 
00028 #include "OniCAPI.h"
00029 #include "OniCProperties.h"
00030 
00034 namespace openni
00035 {
00036 
00038 typedef uint16_t                DepthPixel;
00040 typedef uint16_t                Grayscale16Pixel;
00041 
00042 // structs
00043 _ONI_DECLARE_VERSION(Version);
00044 _ONI_DECLARE_RGB888_PIXEL(RGB888Pixel);
00045 _ONI_DECLARE_YUV422_PIXEL(YUV422DoublePixel);
00046 
00048 #if ONI_PLATFORM != ONI_PLATFORM_WIN32
00049 #pragma GCC diagnostic ignored "-Wunused-variable"
00050 #pragma GCC diagnostic push
00051 #endif
00052 static const char* ANY_DEVICE = NULL;
00053 #if ONI_PLATFORM != ONI_PLATFORM_WIN32
00054 #pragma GCC diagnostic pop
00055 #endif
00056 
00061 template<class T>
00062 class Array
00063 {
00064 public:
00068     Array() : m_data(NULL), m_count(0), m_owner(false) {}
00069 
00077     Array(const T* data, int count) : m_owner(false) { _setData(data, count); }
00078 
00082     ~Array()
00083     {
00084         clear();
00085     }
00086 
00091     int getSize() const { return m_count; }
00092 
00096     const T& operator[](int index) const {return m_data[index];}
00097 
00108     void _setData(const T* data, int count, bool isOwner = false)
00109     {
00110         clear();
00111         m_count = count;
00112         m_owner = isOwner;
00113         if (!isOwner)
00114         {
00115             m_data = data;
00116         }
00117         else
00118         {
00119             m_data = new T[count];
00120             memcpy((void*)m_data, data, count*sizeof(T));
00121         }
00122     }
00123 
00124 private:
00125     Array(const Array<T>&);
00126     Array<T>& operator=(const Array<T>&);
00127 
00128     void clear()
00129     {
00130         if (m_owner && m_data != NULL)
00131             delete []m_data;
00132         m_owner = false;
00133         m_data = NULL;
00134         m_count = 0;
00135     }
00136 
00137     const T* m_data;
00138     int m_count;
00139     bool m_owner;
00140 };
00141 
00156 class VideoMode : private OniVideoMode
00157 {
00158 public:
00164     VideoMode()
00165     {}
00166 
00172     VideoMode(const VideoMode& other)
00173     {
00174         *this = other;
00175     }
00176 
00183     VideoMode& operator=(const VideoMode& other)
00184     {
00185         setPixelFormat(other.getPixelFormat());
00186         setResolution(other.getResolutionX(), other.getResolutionY());
00187         setFps(other.getFps());
00188 
00189         return *this;
00190     }
00191 
00196     PixelFormat getPixelFormat() const { return (PixelFormat)pixelFormat; }
00197 
00202     int getResolutionX() const { return resolutionX; }
00203 
00208     int getResolutionY() const {return resolutionY;}
00209 
00214     int getFps() const { return fps; }
00215 
00222     void setPixelFormat(PixelFormat format) { this->pixelFormat = (OniPixelFormat)format; }
00223 
00231     void setResolution(int resolutionX, int resolutionY)
00232     {
00233         this->resolutionX = resolutionX;
00234         this->resolutionY = resolutionY;
00235     }
00236 
00243     void setFps(int fps) { this->fps = fps; }
00244 
00245     friend class SensorInfo;
00246     friend class VideoStream;
00247     friend class VideoFrameRef;
00248 };
00249 
00267 class SensorInfo
00268 {
00269 public:
00274     SensorType getSensorType() const { return (SensorType)m_pInfo->sensorType; }
00275 
00283     const Array<VideoMode>& getSupportedVideoModes() const { return m_videoModes; }
00284 
00285 private:
00286     SensorInfo(const SensorInfo&);
00287     SensorInfo& operator=(const SensorInfo&);
00288 
00289     SensorInfo() : m_pInfo(NULL), m_videoModes(NULL, 0) {}
00290 
00291     SensorInfo(const OniSensorInfo* pInfo) : m_pInfo(NULL), m_videoModes(NULL, 0)
00292     {
00293         _setInternal(pInfo);
00294     }
00295 
00296     void _setInternal(const OniSensorInfo* pInfo)
00297     {
00298         m_pInfo = pInfo;
00299         if (pInfo == NULL)
00300         {
00301             m_videoModes._setData(NULL, 0);
00302         }
00303         else
00304         {
00305             m_videoModes._setData(static_cast<VideoMode*>(pInfo->pSupportedVideoModes), pInfo->numSupportedVideoModes);
00306         }
00307     }
00308 
00309     const OniSensorInfo* m_pInfo;
00310     Array<VideoMode> m_videoModes;
00311 
00312     friend class VideoStream;
00313     friend class Device;
00314 };
00315 
00325 class DeviceInfo : private OniDeviceInfo
00326 {
00327 public:
00332     const char* getUri() const { return uri; }
00334     const char* getVendor() const { return vendor; }
00336     const char* getName() const { return name; }
00338     uint16_t getUsbVendorId() const { return usbVendorId; }
00340     uint16_t getUsbProductId() const { return usbProductId; }
00341 
00342     friend class Device;
00343     friend class OpenNI;
00344 };
00345 
00359 class VideoFrameRef
00360 {
00361 public:
00366     VideoFrameRef()
00367     {
00368         m_pFrame = NULL;
00369     }
00370 
00374     ~VideoFrameRef()
00375     {
00376         release();
00377     }
00378 
00384     VideoFrameRef(const VideoFrameRef& other) : m_pFrame(NULL)
00385     {
00386         _setFrame(other.m_pFrame);
00387     }
00388 
00394     VideoFrameRef& operator=(const VideoFrameRef& other)
00395     {
00396         _setFrame(other.m_pFrame);
00397         return *this;
00398     }
00399 
00405     inline int getDataSize() const
00406     {
00407         return m_pFrame->dataSize;
00408     }
00409 
00415     inline const void* getData() const
00416     {
00417         return m_pFrame->data;
00418     }
00419 
00426     inline SensorType getSensorType() const
00427     {
00428         return (SensorType)m_pFrame->sensorType;
00429     }
00430 
00438     inline const VideoMode& getVideoMode() const
00439     {
00440         return static_cast<const VideoMode&>(m_pFrame->videoMode);
00441     }
00442 
00450     inline uint64_t getTimestamp() const
00451     {
00452         return m_pFrame->timestamp;
00453     }
00454 
00465     inline int getFrameIndex() const
00466     {
00467         return m_pFrame->frameIndex;
00468     }
00469 
00476     inline int getWidth() const
00477     {
00478         return m_pFrame->width;
00479     }
00480 
00486     inline int getHeight() const
00487     {
00488         return m_pFrame->height;
00489     }
00490 
00495     inline bool getCroppingEnabled() const
00496     {
00497         return m_pFrame->croppingEnabled == TRUE;
00498     }
00499 
00504     inline int getCropOriginX() const
00505     {
00506         return m_pFrame->cropOriginX;
00507     }
00508 
00513     inline int getCropOriginY() const
00514     {
00515         return m_pFrame->cropOriginY;
00516     }
00517 
00523     inline int getStrideInBytes() const
00524     {
00525         return m_pFrame->stride;
00526     }
00527 
00531     inline bool isValid() const
00532     {
00533         return m_pFrame != NULL;
00534     }
00535 
00540     void release()
00541     {
00542         if (m_pFrame != NULL)
00543         {
00544             oniFrameRelease(m_pFrame);
00545             m_pFrame = NULL;
00546         }
00547     }
00548 
00550     void _setFrame(OniFrame* pFrame)
00551     {
00552         setReference(pFrame);
00553         if (pFrame != NULL)
00554         {
00555             oniFrameAddRef(pFrame);
00556         }
00557     }
00558 
00560     OniFrame* _getFrame()
00561     {
00562         return m_pFrame;
00563     }
00564 
00565 private:
00566     friend class VideoStream;
00567     inline void setReference(OniFrame* pFrame)
00568     {
00569         // Initial - don't addref. This is the reference from OpenNI
00570         release();
00571         m_pFrame = pFrame;
00572     }
00573 
00574     OniFrame* m_pFrame; // const!!?
00575 };
00576 
00577 
00578 class Device;
00579 
00601 class CameraSettings;
00602 
00603 class VideoStream
00604 {
00605 public:
00613     class NewFrameListener
00614     {
00615     public:
00619         NewFrameListener() : m_callbackHandle(NULL)
00620         {
00621         }
00622 
00626         virtual void onNewFrame(VideoStream&) = 0;
00627 
00628     private:
00629         friend class VideoStream;
00630 
00631         static void ONI_CALLBACK_TYPE callback(OniStreamHandle streamHandle, void* pCookie)
00632         {
00633             NewFrameListener* pListener = (NewFrameListener*)pCookie;
00634             VideoStream stream;
00635             stream._setHandle(streamHandle);
00636             pListener->onNewFrame(stream);
00637             stream._setHandle(NULL);
00638         }
00639         OniCallbackHandle m_callbackHandle;
00640     };
00641 
00646     VideoStream() : m_stream(NULL), m_sensorInfo(), m_pCameraSettings(NULL)
00647     {}
00648 
00653     ~VideoStream()
00654     {
00655         destroy();
00656     }
00657 
00662     bool isValid() const
00663     {
00664         return m_stream != NULL;
00665     }
00666 
00676     inline Status create(const Device& device, SensorType sensorType);
00677 
00683     inline void destroy();
00684 
00693     const SensorInfo& getSensorInfo() const
00694     {
00695         return m_sensorInfo;
00696     }
00697 
00701     Status start()
00702     {
00703         if (!isValid())
00704         {
00705             return STATUS_ERROR;
00706         }
00707 
00708         return (Status)oniStreamStart(m_stream);
00709     }
00710 
00714     void stop()
00715     {
00716         if (!isValid())
00717         {
00718             return;
00719         }
00720 
00721         oniStreamStop(m_stream);
00722     }
00723 
00734     Status readFrame(VideoFrameRef* pFrame)
00735     {
00736         if (!isValid())
00737         {
00738             return STATUS_ERROR;
00739         }
00740 
00741         OniFrame* pOniFrame;
00742         Status rc = (Status)oniStreamReadFrame(m_stream, &pOniFrame);
00743 
00744         pFrame->setReference(pOniFrame);
00745         return rc;
00746     }
00747 
00755     Status addNewFrameListener(NewFrameListener* pListener)
00756     {
00757         if (!isValid())
00758         {
00759             return STATUS_ERROR;
00760         }
00761         if (pListener->m_callbackHandle != NULL)
00762         {
00763             return STATUS_ERROR;
00764         }
00765 
00766         return (Status)oniStreamRegisterNewFrameCallback(m_stream, pListener->callback, pListener, &pListener->m_callbackHandle);
00767     }
00768 
00773     void removeNewFrameListener(NewFrameListener* pListener)
00774     {
00775         if (!isValid())
00776         {
00777             return;
00778         }
00779 
00780         oniStreamUnregisterNewFrameCallback(m_stream, pListener->m_callbackHandle);
00781         pListener->m_callbackHandle = NULL;
00782     }
00783 
00788     OniStreamHandle _getHandle() const
00789     {
00790         return m_stream;
00791     }
00792 
00797     CameraSettings* getCameraSettings() {return m_pCameraSettings;}
00798 
00809     Status getProperty(int propertyId, void* data, int* dataSize) const
00810     {
00811         if (!isValid())
00812         {
00813             return STATUS_ERROR;
00814         }
00815 
00816         return (Status)oniStreamGetProperty(m_stream, propertyId, data, dataSize);
00817     }
00818 
00829     Status setProperty(int propertyId, const void* data, int dataSize)
00830     {
00831         if (!isValid())
00832         {
00833             return STATUS_ERROR;
00834         }
00835 
00836         return (Status)oniStreamSetProperty(m_stream, propertyId, data, dataSize);
00837     }
00838 
00845     VideoMode getVideoMode() const
00846     {
00847         VideoMode videoMode;
00848         getProperty<OniVideoMode>(STREAM_PROPERTY_VIDEO_MODE, static_cast<OniVideoMode*>(&videoMode));
00849         return videoMode;
00850     }
00851 
00860     Status setVideoMode(const VideoMode& videoMode)
00861     {
00862         return setProperty<OniVideoMode>(STREAM_PROPERTY_VIDEO_MODE, static_cast<const OniVideoMode&>(videoMode));
00863     }
00864 
00870     int getMaxPixelValue() const
00871     {
00872         int maxValue;
00873         Status rc = getProperty<int>(STREAM_PROPERTY_MAX_VALUE, &maxValue);
00874         if (rc != STATUS_OK)
00875         {
00876             return 0;
00877         }
00878         return maxValue;
00879     }
00880 
00886     int getMinPixelValue() const
00887     {
00888         int minValue;
00889         Status rc = getProperty<int>(STREAM_PROPERTY_MIN_VALUE, &minValue);
00890         if (rc != STATUS_OK)
00891         {
00892             return 0;
00893         }
00894         return minValue;
00895     }
00896 
00901     bool isCroppingSupported() const
00902     {
00903         return isPropertySupported(STREAM_PROPERTY_CROPPING);
00904     }
00905 
00914     bool getCropping(int* pOriginX, int* pOriginY, int* pWidth, int* pHeight) const
00915     {
00916         OniCropping cropping;
00917         bool enabled = false;
00918 
00919         Status rc = getProperty<OniCropping>(STREAM_PROPERTY_CROPPING, &cropping);
00920 
00921         if (rc == STATUS_OK)
00922         {
00923             *pOriginX = cropping.originX;
00924             *pOriginY = cropping.originY;
00925             *pWidth = cropping.width;
00926             *pHeight = cropping.height;
00927             enabled = (cropping.enabled == TRUE);
00928         }
00929 
00930         return enabled;
00931     }
00932 
00942     Status setCropping(int originX, int originY, int width, int height)
00943     {
00944         OniCropping cropping;
00945         cropping.enabled = true;
00946         cropping.originX = originX;
00947         cropping.originY = originY;
00948         cropping.width = width;
00949         cropping.height = height;
00950         return setProperty<OniCropping>(STREAM_PROPERTY_CROPPING, cropping);
00951     }
00952 
00957     Status resetCropping()
00958     {
00959         OniCropping cropping;
00960         cropping.enabled = false;
00961         return setProperty<OniCropping>(STREAM_PROPERTY_CROPPING, cropping);
00962     }
00963 
00968     bool getMirroringEnabled() const
00969     {
00970         OniBool enabled;
00971         Status rc = getProperty<OniBool>(STREAM_PROPERTY_MIRRORING, &enabled);
00972         if (rc != STATUS_OK)
00973         {
00974             return false;
00975         }
00976         return enabled == TRUE;
00977     }
00978 
00984     Status setMirroringEnabled(bool isEnabled)
00985     {
00986         return setProperty<OniBool>(STREAM_PROPERTY_MIRRORING, isEnabled ? TRUE : FALSE);
00987     }
00988 
00993     float getHorizontalFieldOfView() const
00994     {
00995         float horizontal = 0;
00996         getProperty<float>(STREAM_PROPERTY_HORIZONTAL_FOV, &horizontal);
00997         return horizontal;
00998     }
00999 
01004     float getVerticalFieldOfView() const
01005     {
01006         float vertical = 0;
01007         getProperty<float>(STREAM_PROPERTY_VERTICAL_FOV, &vertical);
01008         return vertical;
01009     }
01010 
01020     template <class T>
01021     Status setProperty(int propertyId, const T& value)
01022     {
01023         return setProperty(propertyId, &value, sizeof(T));
01024     }
01025 
01035     template <class T>
01036     Status getProperty(int propertyId, T* value) const
01037     {
01038         int size = sizeof(T);
01039         return getProperty(propertyId, value, &size);
01040     }
01041 
01047     bool isPropertySupported(int propertyId) const
01048     {
01049         if (!isValid())
01050         {
01051             return false;
01052         }
01053 
01054         return oniStreamIsPropertySupported(m_stream, propertyId) == TRUE;
01055     }
01056 
01066     Status invoke(int commandId, void* data, int dataSize)
01067     {
01068         if (!isValid())
01069         {
01070             return STATUS_ERROR;
01071         }
01072 
01073         return (Status)oniStreamInvoke(m_stream, commandId, data, dataSize);
01074     }
01075 
01085     template <class T>
01086     Status invoke(int commandId, const T& value)
01087     {
01088         return invoke(commandId, &value, sizeof(T));
01089     }
01090 
01096     bool isCommandSupported(int commandId) const
01097     {
01098         if (!isValid())
01099         {
01100             return false;
01101         }
01102 
01103         return (Status)oniStreamIsCommandSupported(m_stream, commandId) == TRUE;
01104     }
01105 
01106 private:
01107     friend class Device;
01108 
01109     void _setHandle(OniStreamHandle stream)
01110     {
01111         m_sensorInfo._setInternal(NULL);
01112         m_stream = stream;
01113 
01114         if (stream != NULL)
01115         {
01116             m_sensorInfo._setInternal(oniStreamGetSensorInfo(m_stream));
01117         }
01118     }
01119 
01120 private:
01121     VideoStream(const VideoStream& other);
01122     VideoStream& operator=(const VideoStream& other);
01123 
01124     OniStreamHandle m_stream;
01125     SensorInfo m_sensorInfo;
01126     CameraSettings* m_pCameraSettings;
01127 };
01128 
01129 class PlaybackControl;
01130 
01147 class Device
01148 {
01149 public:
01154     Device() : m_pPlaybackControl(NULL), m_device(NULL)
01155     {
01156         clearSensors();
01157     }
01158 
01163     ~Device()
01164     {
01165         if (m_device != NULL)
01166         {
01167             close();
01168         }
01169     }
01170 
01200     inline Status open(const char* uri);
01201 
01207     inline void close();
01208 
01218     const DeviceInfo& getDeviceInfo() const
01219     {
01220         return m_deviceInfo;
01221     }
01222 
01230     bool hasSensor(SensorType sensorType)
01231     {
01232         int i;
01233         for (i = 0; (i < ONI_MAX_SENSORS) && (m_aSensorInfo[i].m_pInfo != NULL); ++i)
01234         {
01235             if (m_aSensorInfo[i].getSensorType() == sensorType)
01236             {
01237                 return true;
01238             }
01239         }
01240 
01241         if (i == ONI_MAX_SENSORS)
01242         {
01243             return false;
01244         }
01245 
01246         const OniSensorInfo* pInfo = oniDeviceGetSensorInfo(m_device, (OniSensorType)sensorType);
01247 
01248         if (pInfo == NULL)
01249         {
01250             return false;
01251         }
01252 
01253         m_aSensorInfo[i]._setInternal(pInfo);
01254 
01255         return true;
01256     }
01257 
01265     const SensorInfo* getSensorInfo(SensorType sensorType)
01266     {
01267         int i;
01268         for (i = 0; (i < ONI_MAX_SENSORS) && (m_aSensorInfo[i].m_pInfo != NULL); ++i)
01269         {
01270             if (m_aSensorInfo[i].getSensorType() == sensorType)
01271             {
01272                 return &m_aSensorInfo[i];
01273             }
01274         }
01275 
01276         // not found. check to see we have additional space
01277         if (i == ONI_MAX_SENSORS)
01278         {
01279             return NULL;
01280         }
01281 
01282         const OniSensorInfo* pInfo = oniDeviceGetSensorInfo(m_device, (OniSensorType)sensorType);
01283         if (pInfo == NULL)
01284         {
01285             return NULL;
01286         }
01287 
01288         m_aSensorInfo[i]._setInternal(pInfo);
01289         return &m_aSensorInfo[i];
01290     }
01291 
01296     OniDeviceHandle _getHandle() const
01297     {
01298         return m_device;
01299     }
01300 
01305     PlaybackControl* getPlaybackControl() {return m_pPlaybackControl;}
01306 
01318     Status getProperty(int propertyId, void* data, int* dataSize) const
01319     {
01320         return (Status)oniDeviceGetProperty(m_device, propertyId, data, dataSize);
01321     }
01322 
01334     Status setProperty(int propertyId, const void* data, int dataSize)
01335     {
01336         return (Status)oniDeviceSetProperty(m_device, propertyId, data, dataSize);
01337     }
01338 
01346     bool isImageRegistrationModeSupported(ImageRegistrationMode mode) const
01347     {
01348         return (oniDeviceIsImageRegistrationModeSupported(m_device, (OniImageRegistrationMode)mode) == TRUE);
01349     }
01350 
01358     ImageRegistrationMode getImageRegistrationMode() const
01359     {
01360         ImageRegistrationMode mode;
01361         Status rc = getProperty<ImageRegistrationMode>(DEVICE_PROPERTY_IMAGE_REGISTRATION, &mode);
01362         if (rc != STATUS_OK)
01363         {
01364             return IMAGE_REGISTRATION_OFF;
01365         }
01366         return mode;
01367     }
01368 
01382     Status setImageRegistrationMode(ImageRegistrationMode mode)
01383     {
01384         return setProperty<ImageRegistrationMode>(DEVICE_PROPERTY_IMAGE_REGISTRATION, mode);
01385     }
01386 
01391     bool isValid() const
01392     {
01393         return m_device != NULL;
01394     }
01395 
01400     bool isFile() const
01401     {
01402         return isPropertySupported(DEVICE_PROPERTY_PLAYBACK_SPEED) &&
01403             isPropertySupported(DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED) &&
01404             isCommandSupported(DEVICE_COMMAND_SEEK);
01405     }
01406 
01415     Status setDepthColorSyncEnabled(bool isEnabled)
01416     {
01417         Status rc = STATUS_OK;
01418 
01419         if (isEnabled)
01420         {
01421             rc = (Status)oniDeviceEnableDepthColorSync(m_device);
01422         }
01423         else
01424         {
01425             oniDeviceDisableDepthColorSync(m_device);
01426         }
01427 
01428         return rc;
01429     }
01430 
01441     template <class T>
01442     Status setProperty(int propertyId, const T& value)
01443     {
01444         return setProperty(propertyId, &value, sizeof(T));
01445     }
01446 
01456     template <class T>
01457     Status getProperty(int propertyId, T* value) const
01458     {
01459         int size = sizeof(T);
01460         return getProperty(propertyId, value, &size);
01461     }
01462 
01468     bool isPropertySupported(int propertyId) const
01469     {
01470         return oniDeviceIsPropertySupported(m_device, propertyId) == TRUE;
01471     }
01472 
01482     Status invoke(int commandId, const void* data, int dataSize)
01483     {
01484         return (Status)oniDeviceInvoke(m_device, commandId, data, dataSize);
01485     }
01486 
01496     template <class T>
01497     Status invoke(int propertyId, const T& value)
01498     {
01499         return invoke(propertyId, &value, sizeof(T));
01500     }
01501 
01507     bool isCommandSupported(int commandId) const
01508     {
01509         return oniDeviceIsCommandSupported(m_device, commandId) == TRUE;
01510     }
01511 
01512 private:
01513     Device(const Device&);
01514     Device& operator=(const Device&);
01515 
01516     void clearSensors()
01517     {
01518         for (int i = 0; i < ONI_MAX_SENSORS; ++i)
01519         {
01520             m_aSensorInfo[i]._setInternal(NULL);
01521         }
01522     }
01523 
01524     Status _setHandle(OniDeviceHandle deviceHandle)
01525     {
01526         if (m_device == NULL)
01527         {
01528             m_device = deviceHandle;
01529 
01530             clearSensors();
01531 
01532             oniDeviceGetInfo(m_device, &m_deviceInfo);
01533             // Read deviceInfo
01534             return STATUS_OK;
01535         }
01536 
01537         return STATUS_OUT_OF_FLOW;
01538     }
01539 
01540 private:
01541     PlaybackControl* m_pPlaybackControl;
01542 
01543     OniDeviceHandle m_device;
01544     DeviceInfo m_deviceInfo;
01545     SensorInfo m_aSensorInfo[ONI_MAX_SENSORS];
01546 };
01547 
01561 class PlaybackControl
01562 {
01563 public:
01564 
01570     ~PlaybackControl()
01571     {
01572         detach();
01573     }
01574 
01595     float getSpeed() const
01596     {
01597         if (!isValid())
01598         {
01599             return 0.0f;
01600         }
01601         float speed;
01602         Status rc = m_pDevice->getProperty<float>(DEVICE_PROPERTY_PLAYBACK_SPEED, &speed);
01603         if (rc != STATUS_OK)
01604         {
01605             return 1.0f;
01606         }
01607         return speed;
01608     }
01616     Status setSpeed(float speed)
01617     {
01618         if (!isValid())
01619         {
01620             return STATUS_NO_DEVICE;
01621         }
01622         return m_pDevice->setProperty<float>(DEVICE_PROPERTY_PLAYBACK_SPEED, speed);
01623     }
01624 
01630     bool getRepeatEnabled() const
01631     {
01632         if (!isValid())
01633         {
01634             return false;
01635         }
01636 
01637         OniBool repeat;
01638         Status rc = m_pDevice->getProperty<OniBool>(DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED, &repeat);
01639         if (rc != STATUS_OK)
01640         {
01641             return false;
01642         }
01643 
01644         return repeat == TRUE;
01645     }
01646 
01655     Status setRepeatEnabled(bool repeat)
01656     {
01657         if (!isValid())
01658         {
01659             return STATUS_NO_DEVICE;
01660         }
01661 
01662         return m_pDevice->setProperty<OniBool>(DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED, repeat ? TRUE : FALSE);
01663     }
01664 
01675     Status seek(const VideoStream& stream, int frameIndex)
01676     {
01677         if (!isValid())
01678         {
01679             return STATUS_NO_DEVICE;
01680         }
01681         OniSeek seek;
01682         seek.frameIndex = frameIndex;
01683         seek.stream = stream._getHandle();
01684         return m_pDevice->invoke(DEVICE_COMMAND_SEEK, seek);
01685     }
01686 
01695     int getNumberOfFrames(const VideoStream& stream) const
01696     {
01697         int numOfFrames = -1;
01698         Status rc = stream.getProperty<int>(STREAM_PROPERTY_NUMBER_OF_FRAMES, &numOfFrames);
01699         if (rc != STATUS_OK)
01700         {
01701             return 0;
01702         }
01703         return numOfFrames;
01704     }
01705 
01706     bool isValid() const
01707     {
01708         return m_pDevice != NULL;
01709     }
01710 private:
01711     Status attach(Device* device)
01712     {
01713         if (!device->isValid() || !device->isFile())
01714         {
01715             return STATUS_ERROR;
01716         }
01717 
01718         detach();
01719         m_pDevice = device;
01720 
01721         return STATUS_OK;
01722     }
01723     void detach()
01724     {
01725         m_pDevice = NULL;
01726     }
01727 
01728     friend class Device;
01729     PlaybackControl(Device* pDevice) : m_pDevice(NULL)
01730     {
01731         if (pDevice != NULL)
01732         {
01733             attach(pDevice);
01734         }
01735     }
01736 
01737     Device* m_pDevice;
01738 };
01739 
01740 class CameraSettings
01741 {
01742 public:
01743     // setters
01744     Status setAutoExposureEnabled(bool enabled)
01745     {
01746         return setProperty(STREAM_PROPERTY_AUTO_EXPOSURE, enabled ? TRUE : FALSE);
01747     }
01748     Status setAutoWhiteBalanceEnabled(bool enabled)
01749     {
01750         return setProperty(STREAM_PROPERTY_AUTO_WHITE_BALANCE, enabled ? TRUE : FALSE);
01751     }
01752 
01753     bool getAutoExposureEnabled() const
01754     {
01755         OniBool enabled = FALSE;
01756 
01757         Status rc = getProperty(STREAM_PROPERTY_AUTO_EXPOSURE, &enabled);
01758         return rc == STATUS_OK && enabled == TRUE;
01759     }
01760     bool getAutoWhiteBalanceEnabled() const
01761     {
01762         OniBool enabled = FALSE;
01763 
01764         Status rc = getProperty(STREAM_PROPERTY_AUTO_WHITE_BALANCE, &enabled);
01765         return rc == STATUS_OK && enabled == TRUE;
01766     }
01767 
01768     bool isValid() const {return m_pStream != NULL;}
01769 private:
01770     template <class T>
01771     Status getProperty(int propertyId, T* value) const
01772     {
01773         if (!isValid()) return STATUS_NOT_SUPPORTED;
01774 
01775         return m_pStream->getProperty<T>(propertyId, value);
01776     }
01777     template <class T>
01778     Status setProperty(int propertyId, const T& value)
01779     {
01780         if (!isValid()) return STATUS_NOT_SUPPORTED;
01781 
01782         return m_pStream->setProperty<T>(propertyId, value);
01783     }
01784 
01785     friend class VideoStream;
01786     CameraSettings(VideoStream* pStream)
01787     {
01788         m_pStream = pStream;
01789     }
01790 
01791     VideoStream* m_pStream;
01792 };
01793 
01794 
01807 class OpenNI
01808 {
01809 public:
01810 
01826     class DeviceConnectedListener
01827     {
01828     public:
01829         DeviceConnectedListener()
01830         {
01831             m_deviceConnectedCallbacks.deviceConnected = deviceConnectedCallback;
01832             m_deviceConnectedCallbacks.deviceDisconnected = NULL;
01833             m_deviceConnectedCallbacks.deviceStateChanged = NULL;
01834             m_deviceConnectedCallbacksHandle = NULL;
01835         }
01847         virtual void onDeviceConnected(const DeviceInfo*) = 0;
01848     private:
01849         static void ONI_CALLBACK_TYPE deviceConnectedCallback(const OniDeviceInfo* pInfo, void* pCookie)
01850         {
01851             DeviceConnectedListener* pListener = (DeviceConnectedListener*)pCookie;
01852             pListener->onDeviceConnected(static_cast<const DeviceInfo*>(pInfo));
01853         }
01854 
01855         friend class OpenNI;
01856         OniDeviceCallbacks m_deviceConnectedCallbacks;
01857         OniCallbackHandle m_deviceConnectedCallbacksHandle;
01858 
01859     };
01876     class DeviceDisconnectedListener
01877     {
01878     public:
01879         DeviceDisconnectedListener()
01880         {
01881             m_deviceDisconnectedCallbacks.deviceConnected = NULL;
01882             m_deviceDisconnectedCallbacks.deviceDisconnected = deviceDisconnectedCallback;
01883             m_deviceDisconnectedCallbacks.deviceStateChanged = NULL;
01884             m_deviceDisconnectedCallbacksHandle = NULL;
01885         }
01894         virtual void onDeviceDisconnected(const DeviceInfo*) = 0;
01895     private:
01896         static void ONI_CALLBACK_TYPE deviceDisconnectedCallback(const OniDeviceInfo* pInfo, void* pCookie)
01897         {
01898             DeviceDisconnectedListener* pListener = (DeviceDisconnectedListener*)pCookie;
01899             pListener->onDeviceDisconnected(static_cast<const DeviceInfo*>(pInfo));
01900         }
01901 
01902         friend class OpenNI;
01903         OniDeviceCallbacks m_deviceDisconnectedCallbacks;
01904         OniCallbackHandle m_deviceDisconnectedCallbacksHandle;
01905     };
01919     class DeviceStateChangedListener
01920     {
01921     public:
01922         DeviceStateChangedListener()
01923         {
01924             m_deviceStateChangedCallbacks.deviceConnected = NULL;
01925             m_deviceStateChangedCallbacks.deviceDisconnected = NULL;
01926             m_deviceStateChangedCallbacks.deviceStateChanged = deviceStateChangedCallback;
01927             m_deviceStateChangedCallbacksHandle = NULL;
01928         }
01935         virtual void onDeviceStateChanged(const DeviceInfo*, DeviceState) = 0;
01936     private:
01937         static void ONI_CALLBACK_TYPE deviceStateChangedCallback(const OniDeviceInfo* pInfo, OniDeviceState state, void* pCookie)
01938         {
01939             DeviceStateChangedListener* pListener = (DeviceStateChangedListener*)pCookie;
01940             pListener->onDeviceStateChanged(static_cast<const DeviceInfo*>(pInfo), DeviceState(state));
01941         }
01942 
01943         friend class OpenNI;
01944         OniDeviceCallbacks m_deviceStateChangedCallbacks;
01945         OniCallbackHandle m_deviceStateChangedCallbacksHandle;
01946     };
01947 
01953     static Status initialize()
01954     {
01955         return (Status)oniInitialize(ONI_API_VERSION); // provide version of API, to make sure proper struct sizes are used
01956     }
01957 
01962     static void shutdown()
01963     {
01964         oniShutdown();
01965     }
01966 
01970     static Version getVersion()
01971     {
01972         OniVersion version = oniGetVersion();
01973         union
01974         {
01975             OniVersion* pC;
01976             Version* pCpp;
01977         } a;
01978         a.pC = &version;
01979         return *a.pCpp;
01980     }
01981 
01989     static const char* getExtendedError()
01990     {
01991         return oniGetExtendedError();
01992     }
01993 
01998     static void enumerateDevices(Array<DeviceInfo>* deviceInfoList)
01999     {
02000         OniDeviceInfo* m_pDeviceInfos;
02001         int m_deviceInfoCount;
02002         oniGetDeviceList(&m_pDeviceInfos, &m_deviceInfoCount);
02003         deviceInfoList->_setData((DeviceInfo*)m_pDeviceInfos, m_deviceInfoCount, true);
02004         oniReleaseDeviceList(m_pDeviceInfos);
02005     }
02006 
02015     static Status waitForAnyStream(VideoStream** pStreams, int streamCount, int* pReadyStreamIndex, int timeout = TIMEOUT_FOREVER)
02016     {
02017         static const int ONI_MAX_STREAMS = 50;
02018         OniStreamHandle streams[ONI_MAX_STREAMS];
02019 
02020         if (streamCount > ONI_MAX_STREAMS)
02021         {
02022             printf("Too many streams for wait: %d > %d\n", streamCount, ONI_MAX_STREAMS);
02023             return STATUS_BAD_PARAMETER;
02024         }
02025 
02026         *pReadyStreamIndex = -1;
02027         for (int i = 0; i < streamCount; ++i)
02028         {
02029             if (pStreams[i] != NULL)
02030             {
02031                 streams[i] = pStreams[i]->_getHandle();
02032             }
02033             else
02034             {
02035                 streams[i] = NULL;
02036             }
02037         }
02038         Status rc = (Status)oniWaitForAnyStream(streams, streamCount, pReadyStreamIndex, timeout);
02039 
02040         return rc;
02041     }
02042 
02050     static Status addDeviceConnectedListener(DeviceConnectedListener* pListener)
02051     {
02052         if (pListener->m_deviceConnectedCallbacksHandle != NULL)
02053         {
02054             return STATUS_ERROR;
02055         }
02056         return (Status)oniRegisterDeviceCallbacks(&pListener->m_deviceConnectedCallbacks, pListener, &pListener->m_deviceConnectedCallbacksHandle);
02057     }
02065     static Status addDeviceDisconnectedListener(DeviceDisconnectedListener* pListener)
02066     {
02067         if (pListener->m_deviceDisconnectedCallbacksHandle != NULL)
02068         {
02069             return STATUS_ERROR;
02070         }
02071         return (Status)oniRegisterDeviceCallbacks(&pListener->m_deviceDisconnectedCallbacks, pListener, &pListener->m_deviceDisconnectedCallbacksHandle);
02072     }
02080     static Status addDeviceStateChangedListener(DeviceStateChangedListener* pListener)
02081     {
02082         if (pListener->m_deviceStateChangedCallbacksHandle != NULL)
02083         {
02084             return STATUS_ERROR;
02085         }
02086         return (Status)oniRegisterDeviceCallbacks(&pListener->m_deviceStateChangedCallbacks, pListener, &pListener->m_deviceStateChangedCallbacksHandle);
02087     }
02095     static void removeDeviceConnectedListener(DeviceConnectedListener* pListener)
02096     {
02097         oniUnregisterDeviceCallbacks(pListener->m_deviceConnectedCallbacksHandle);
02098         pListener->m_deviceConnectedCallbacksHandle = NULL;
02099     }
02107     static void removeDeviceDisconnectedListener(DeviceDisconnectedListener* pListener)
02108     {
02109         oniUnregisterDeviceCallbacks(pListener->m_deviceDisconnectedCallbacksHandle);
02110         pListener->m_deviceDisconnectedCallbacksHandle = NULL;
02111     }
02119     static void removeDeviceStateChangedListener(DeviceStateChangedListener* pListener)
02120     {
02121         oniUnregisterDeviceCallbacks(pListener->m_deviceStateChangedCallbacksHandle);
02122         pListener->m_deviceStateChangedCallbacksHandle = NULL;
02123     }
02124 private:
02125     OpenNI()
02126     {
02127     }
02128 };
02129 
02165 class CoordinateConverter
02166 {
02167 public:
02178     static Status convertWorldToDepth(const VideoStream& depthStream, float worldX, float worldY, float worldZ, int* pDepthX, int* pDepthY, DepthPixel* pDepthZ)
02179     {
02180         float depthX, depthY, depthZ;
02181         Status rc = (Status)oniCoordinateConverterWorldToDepth(depthStream._getHandle(), worldX, worldY, worldZ, &depthX, &depthY, &depthZ);
02182         *pDepthX = (int)depthX;
02183         *pDepthY = (int)depthY;
02184         *pDepthZ = (DepthPixel)depthZ;
02185         return rc;
02186     }
02187 
02198     static Status convertWorldToDepth(const VideoStream& depthStream, float worldX, float worldY, float worldZ, float* pDepthX, float* pDepthY, float* pDepthZ)
02199     {
02200         return (Status)oniCoordinateConverterWorldToDepth(depthStream._getHandle(), worldX, worldY, worldZ, pDepthX, pDepthY, pDepthZ);
02201     }
02202 
02213     static Status convertDepthToWorld(const VideoStream& depthStream, int depthX, int depthY, DepthPixel depthZ, float* pWorldX, float* pWorldY, float* pWorldZ)
02214     {
02215         return (Status)oniCoordinateConverterDepthToWorld(depthStream._getHandle(), float(depthX), float(depthY), float(depthZ), pWorldX, pWorldY, pWorldZ);
02216     }
02217 
02228     static Status convertDepthToWorld(const VideoStream& depthStream, float depthX, float depthY, float depthZ, float* pWorldX, float* pWorldY, float* pWorldZ)
02229     {
02230         return (Status)oniCoordinateConverterDepthToWorld(depthStream._getHandle(), depthX, depthY, depthZ, pWorldX, pWorldY, pWorldZ);
02231     }
02232 
02244     static Status convertDepthToColor(const VideoStream& depthStream, const VideoStream& colorStream, int depthX, int depthY, DepthPixel depthZ, int* pColorX, int* pColorY)
02245     {
02246         return (Status)oniCoordinateConverterDepthToColor(depthStream._getHandle(), colorStream._getHandle(), depthX, depthY, depthZ, pColorX, pColorY);
02247     }
02248 };
02249 
02264 class Recorder
02265 {
02266 public:
02271     Recorder() : m_recorder(NULL)
02272     {
02273     }
02274 
02278     ~Recorder()
02279     {
02280         destroy();
02281     }
02282 
02294     Status create(const char* fileName)
02295     {
02296         if (!isValid())
02297         {
02298             return (Status)oniCreateRecorder(fileName, &m_recorder);
02299         }
02300         return STATUS_ERROR;
02301     }
02302 
02309     bool isValid() const
02310     {
02311         return NULL != getHandle();
02312     }
02313 
02324     Status attach(VideoStream& stream, bool allowLossyCompression = false)
02325     {
02326         if (!isValid() || !stream.isValid())
02327         {
02328             return STATUS_ERROR;
02329         }
02330         return (Status)oniRecorderAttachStream(
02331                 m_recorder,
02332                 stream._getHandle(),
02333                 allowLossyCompression);
02334     }
02335 
02342     Status start()
02343     {
02344         if (!isValid())
02345         {
02346             return STATUS_ERROR;
02347         }
02348         return (Status)oniRecorderStart(m_recorder);
02349     }
02350 
02354     void stop()
02355     {
02356         if (isValid())
02357         {
02358             oniRecorderStop(m_recorder);
02359         }
02360     }
02361 
02365     void destroy()
02366     {
02367         if (isValid())
02368         {
02369             oniRecorderDestroy(&m_recorder);
02370         }
02371     }
02372 
02373 private:
02374     Recorder(const Recorder&);
02375     Recorder& operator=(const Recorder&);
02376 
02380     OniRecorderHandle getHandle() const
02381     {
02382         return m_recorder;
02383     }
02384 
02385 
02386     OniRecorderHandle m_recorder;
02387 };
02388 
02389 // Implemetation
02390 Status VideoStream::create(const Device& device, SensorType sensorType)
02391 {
02392     OniStreamHandle streamHandle;
02393     Status rc = (Status)oniDeviceCreateStream(device._getHandle(), (OniSensorType)sensorType, &streamHandle);
02394     if (rc != STATUS_OK)
02395     {
02396         return rc;
02397     }
02398 
02399     _setHandle(streamHandle);
02400 
02401     if (isPropertySupported(STREAM_PROPERTY_AUTO_WHITE_BALANCE) && isPropertySupported(STREAM_PROPERTY_AUTO_EXPOSURE))
02402     {
02403         m_pCameraSettings = new CameraSettings(this);
02404     }
02405 
02406     return STATUS_OK;
02407 }
02408 
02409 void VideoStream::destroy()
02410 {
02411     if (!isValid())
02412     {
02413         return;
02414     }
02415 
02416     if (m_pCameraSettings != NULL)
02417     {
02418         delete m_pCameraSettings;
02419         m_pCameraSettings = NULL;
02420     }
02421 
02422     if (m_stream != NULL)
02423     {
02424         oniStreamDestroy(m_stream);
02425         m_stream = NULL;
02426     }
02427 }
02428 
02429 Status Device::open(const char* uri)
02430 {
02431     OniDeviceHandle deviceHandle;
02432     Status rc = (Status)oniDeviceOpen(uri, &deviceHandle);
02433     if (rc != STATUS_OK)
02434     {
02435         return rc;
02436     }
02437 
02438     _setHandle(deviceHandle);
02439 
02440     if (isFile())
02441     {
02442         m_pPlaybackControl = new PlaybackControl(this);
02443     }
02444 
02445     return STATUS_OK;
02446 }
02447 
02448 void Device::close()
02449 {
02450     if (m_pPlaybackControl != NULL)
02451     {
02452         delete m_pPlaybackControl;
02453         m_pPlaybackControl = NULL;
02454     }
02455 
02456     if (m_device != NULL)
02457     {
02458         oniDeviceClose(m_device);
02459         m_device = NULL;
02460     }
02461 }
02462 
02463 
02464 }
02465 
02466 #endif // _OPEN_NI_HPP_